mirror of
https://github.com/YunoHost-Apps/kanboard_ynh.git
synced 2024-09-03 19:36:17 +02:00
Update to Kanboard v1.0.19
This commit is contained in:
parent
b4e4669ca3
commit
641c152ed9
367 changed files with 12063 additions and 7777 deletions
|
@ -6,6 +6,9 @@ define('DEBUG', false);
|
||||||
// Debug file path
|
// Debug file path
|
||||||
define('DEBUG_FILE', __DIR__.'/data/debug.log');
|
define('DEBUG_FILE', __DIR__.'/data/debug.log');
|
||||||
|
|
||||||
|
// Plugins directory
|
||||||
|
define('PLUGINS_DIR', 'data/plugins');
|
||||||
|
|
||||||
// Folder for uploaded files, don't forget the trailing slash
|
// Folder for uploaded files, don't forget the trailing slash
|
||||||
define('FILES_DIR', 'data/files/');
|
define('FILES_DIR', 'data/files/');
|
||||||
|
|
||||||
|
@ -65,20 +68,20 @@ define('LDAP_SERVER', '');
|
||||||
// LDAP server port (389 by default)
|
// LDAP server port (389 by default)
|
||||||
define('LDAP_PORT', 389);
|
define('LDAP_PORT', 389);
|
||||||
|
|
||||||
// By default, require certificate to be verified for ldaps:// style URL. Set to false to skip the verification.
|
// By default, require certificate to be verified for ldaps:// style URL. Set to false to skip the verification
|
||||||
define('LDAP_SSL_VERIFY', true);
|
define('LDAP_SSL_VERIFY', true);
|
||||||
|
|
||||||
// Enable LDAP START_TLS
|
// Enable LDAP START_TLS
|
||||||
define('LDAP_START_TLS', false);
|
define('LDAP_START_TLS', false);
|
||||||
|
|
||||||
// LDAP bind type: "anonymous", "user" (use the given user/password from the form) and "proxy" (a specific user to browse the LDAP directory)
|
// LDAP bind type: "anonymous", "user" or "proxy"
|
||||||
define('LDAP_BIND_TYPE', 'anonymous');
|
define('LDAP_BIND_TYPE', 'anonymous');
|
||||||
|
|
||||||
// LDAP username to connect with. null for anonymous bind (by default).
|
// LDAP username to use with proxy mode
|
||||||
// Or for user bind type, you can use a pattern: %s@kanboard.local
|
// LDAP username pattern to use with user mode
|
||||||
define('LDAP_USERNAME', null);
|
define('LDAP_USERNAME', null);
|
||||||
|
|
||||||
// LDAP password to connect with. null for anonymous bind (by default).
|
// LDAP password to use for proxy mode
|
||||||
define('LDAP_PASSWORD', null);
|
define('LDAP_PASSWORD', null);
|
||||||
|
|
||||||
// LDAP account base, i.e. root of all user account
|
// LDAP account base, i.e. root of all user account
|
||||||
|
@ -90,16 +93,27 @@ define('LDAP_ACCOUNT_BASE', '');
|
||||||
// Example for OpenLDAP: 'uid=%s'
|
// Example for OpenLDAP: 'uid=%s'
|
||||||
define('LDAP_USER_PATTERN', '');
|
define('LDAP_USER_PATTERN', '');
|
||||||
|
|
||||||
// Name of an attribute of the user account object which should be used as the full name of the user.
|
// Name of an attribute of the user account object which should be used as the full name of the user
|
||||||
define('LDAP_ACCOUNT_FULLNAME', 'displayname');
|
define('LDAP_ACCOUNT_FULLNAME', 'displayname');
|
||||||
|
|
||||||
// Name of an attribute of the user account object which should be used as the email of the user.
|
// Name of an attribute of the user account object which should be used as the email of the user
|
||||||
define('LDAP_ACCOUNT_EMAIL', 'mail');
|
define('LDAP_ACCOUNT_EMAIL', 'mail');
|
||||||
|
|
||||||
// Name of an attribute of the user account object which should be used as the id of the user.
|
// Name of an attribute of the user account object which should be used as the id of the user. (optional)
|
||||||
// Example for ActiveDirectory: 'samaccountname'
|
// Example for ActiveDirectory: 'samaccountname'
|
||||||
// Example for OpenLDAP: 'uid'
|
// Example for OpenLDAP: 'uid'
|
||||||
define('LDAP_ACCOUNT_ID', 'samaccountname');
|
define('LDAP_ACCOUNT_ID', '');
|
||||||
|
|
||||||
|
// LDAP Attribute for group membership
|
||||||
|
define('LDAP_ACCOUNT_MEMBEROF', 'memberof');
|
||||||
|
|
||||||
|
// DN for administrators
|
||||||
|
// Example: CN=Kanboard Admins,CN=Users,DC=kanboard,DC=local
|
||||||
|
define('LDAP_GROUP_ADMIN_DN', '');
|
||||||
|
|
||||||
|
// DN for project administrators
|
||||||
|
// Example: CN=Kanboard Project Admins,CN=Users,DC=kanboard,DC=local
|
||||||
|
define('LDAP_GROUP_PROJECT_ADMIN_DN', '');
|
||||||
|
|
||||||
// By default Kanboard lowercase the ldap username to avoid duplicate users (the database is case sensitive)
|
// By default Kanboard lowercase the ldap username to avoid duplicate users (the database is case sensitive)
|
||||||
// Set to true if you want to preserve the case
|
// Set to true if you want to preserve the case
|
||||||
|
@ -174,6 +188,9 @@ define('ENABLE_HSTS', true);
|
||||||
// Enable or disable "X-Frame-Options: DENY" HTTP header
|
// Enable or disable "X-Frame-Options: DENY" HTTP header
|
||||||
define('ENABLE_XFRAME', true);
|
define('ENABLE_XFRAME', true);
|
||||||
|
|
||||||
|
// Enable syslog logging
|
||||||
|
define('ENABLE_SYSLOG', true);
|
||||||
|
|
||||||
// Escape html inside markdown text
|
// Escape html inside markdown text
|
||||||
define('MARKDOWN_ESCAPE_HTML', true);
|
define('MARKDOWN_ESCAPE_HTML', true);
|
||||||
|
|
||||||
|
@ -198,3 +215,10 @@ define('BRUTEFORCE_LOCKDOWN_DURATION', 15);
|
||||||
// Session duration in second (0 = until the browser is closed)
|
// Session duration in second (0 = until the browser is closed)
|
||||||
// See http://php.net/manual/en/session.configuration.php#ini.session.cookie-lifetime
|
// See http://php.net/manual/en/session.configuration.php#ini.session.cookie-lifetime
|
||||||
define('SESSION_DURATION', 1);
|
define('SESSION_DURATION', 1);
|
||||||
|
|
||||||
|
// HTTP client proxy
|
||||||
|
define('HTTP_PROXY_HOSTNAME', '');
|
||||||
|
define('HTTP_PROXY_PORT', '3128');
|
||||||
|
define('HTTP_PROXY_USERNAME', '');
|
||||||
|
define('HTTP_PROXY_PASSWORD', '');
|
||||||
|
|
||||||
|
|
|
@ -7,3 +7,20 @@
|
||||||
RewriteCond %{REQUEST_FILENAME} !-f
|
RewriteCond %{REQUEST_FILENAME} !-f
|
||||||
RewriteRule ^ index.php [QSA,L]
|
RewriteRule ^ index.php [QSA,L]
|
||||||
</IfModule>
|
</IfModule>
|
||||||
|
|
||||||
|
<FilesMatch "(kanboard|config.php|config.default.php)">
|
||||||
|
<IfModule mod_version.c>
|
||||||
|
<IfVersion >= 2.3>
|
||||||
|
Require all denied
|
||||||
|
</IfVersion>
|
||||||
|
<IfVersion < 2.3>
|
||||||
|
Order allow,deny
|
||||||
|
Deny from all
|
||||||
|
</IfVersion>
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
<IfModule !mod_version.c>
|
||||||
|
Order allow,deny
|
||||||
|
Deny from all
|
||||||
|
</IfModule>
|
||||||
|
</FilesMatch>
|
||||||
|
|
|
@ -1,3 +1,67 @@
|
||||||
|
Version 1.0.19
|
||||||
|
--------------
|
||||||
|
|
||||||
|
New features:
|
||||||
|
|
||||||
|
* Added web notifications
|
||||||
|
* Added LDAP group sync
|
||||||
|
* Added swimlane description
|
||||||
|
* New plugin system (alpha)
|
||||||
|
* Added Bahasa Indonesia translation
|
||||||
|
* Added API procedures: getMyOverdueTasks, getOverdueTasksByProject and GetMyProjects
|
||||||
|
* Added user API access for procedure getProjectActivity()
|
||||||
|
* Added config parameter to enable/disable Syslog
|
||||||
|
* Added custom filters
|
||||||
|
* Added http client proxy support
|
||||||
|
|
||||||
|
Core functionalities moved to plugins:
|
||||||
|
|
||||||
|
* Budget planning: https://github.com/kanboard/plugin-budget
|
||||||
|
* SubtaskForecast: https://github.com/kanboard/plugin-subtask-forecast
|
||||||
|
* Timetable: https://github.com/kanboard/plugin-timetable
|
||||||
|
|
||||||
|
Improvements:
|
||||||
|
|
||||||
|
* When duplicating a task redirect to the new task
|
||||||
|
* Include more shortcut links into the view "My projects"
|
||||||
|
* Duplicate a project with tasks will copy the new tasks in the same columns
|
||||||
|
* Offer alternative method to create Mysql and Postgres databases (import sql dump)
|
||||||
|
* Make sure there is always a trailing slash for application_url
|
||||||
|
* Do not show the checkbox "Show default swimlane" when there is no active swimlanes
|
||||||
|
* Append filters instead of replacing value for users and categories dropdowns
|
||||||
|
* Do not show empty swimlanes in public view
|
||||||
|
* Change swimlane layout to save space on the screen
|
||||||
|
* Add the possibility to set/unset max column height (column scrolling)
|
||||||
|
* Show "Open this task" in dropdown menu for closed tasks
|
||||||
|
* Show assignee on card only when someone is assigned (hide nobody text)
|
||||||
|
* Highlight selected item in dropdown menus
|
||||||
|
* Gantt chart: change bar color according to task progress
|
||||||
|
* Replace color dropdown by color picker in task forms
|
||||||
|
* Creating another task stay in the popover (no full page refresh anymore)
|
||||||
|
* Avoid scrollbar in Gantt chart for row title on Windows platform
|
||||||
|
* Remove unnecessary margin for calendar header
|
||||||
|
* Show localized documentation if available
|
||||||
|
* Add event subtask.delete
|
||||||
|
* Add abstract storage layer
|
||||||
|
* Add abstract cache layer
|
||||||
|
* Add Docker tag for stable version
|
||||||
|
|
||||||
|
Others:
|
||||||
|
|
||||||
|
* Data directory permissions are not checked anymore
|
||||||
|
* Data directory is not mandatory anymore for people that use a remote database and remote object storage
|
||||||
|
|
||||||
|
Bug fixes:
|
||||||
|
|
||||||
|
* Fix typo in template that prevent the Gitlab OAuth link to be displayed
|
||||||
|
* Fix Markdown preview links focus
|
||||||
|
* Avoid dropdown menu to be truncated inside a column with scrolling
|
||||||
|
* Deleting subtask doesn't update task time tracking
|
||||||
|
* Fix Mysql error about gitlab_id when creating remote user
|
||||||
|
* Fix subtask timer bug (event called recursively)
|
||||||
|
* Fix Postgres issue "Cardinality violation" when there is multiple "is_milestone_of" links
|
||||||
|
* Fix issue with due date greater than year 2038
|
||||||
|
|
||||||
Version 1.0.18
|
Version 1.0.18
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
|
|
@ -1 +1,7 @@
|
||||||
Deny from all
|
<IfVersion >= 2.3>
|
||||||
|
Require all denied
|
||||||
|
</IfVersion>
|
||||||
|
<IfVersion < 2.3>
|
||||||
|
Order allow,deny
|
||||||
|
Deny from all
|
||||||
|
</IfVersion>
|
||||||
|
|
|
@ -126,6 +126,17 @@ abstract class Base extends \Core\Base
|
||||||
return get_called_class();
|
return get_called_class();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get project id
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public function getProjectId()
|
||||||
|
{
|
||||||
|
return $this->project_id;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set an user defined parameter
|
* Set an user defined parameter
|
||||||
*
|
*
|
||||||
|
|
|
@ -64,7 +64,9 @@ class TaskDuplicateAnotherProject extends Base
|
||||||
*/
|
*/
|
||||||
public function doAction(array $data)
|
public function doAction(array $data)
|
||||||
{
|
{
|
||||||
return (bool) $this->taskDuplication->duplicateToProject($data['task_id'], $this->getParam('project_id'));
|
$destination_column_id = $this->board->getFirstColumn($this->getParam('project_id'));
|
||||||
|
|
||||||
|
return (bool) $this->taskDuplication->duplicateToProject($data['task_id'], $this->getParam('project_id'), null, $destination_column_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -19,6 +19,8 @@ abstract class Base extends \Core\Base
|
||||||
'getMyActivityStream',
|
'getMyActivityStream',
|
||||||
'createMyPrivateProject',
|
'createMyPrivateProject',
|
||||||
'getMyProjectsList',
|
'getMyProjectsList',
|
||||||
|
'getMyProjects',
|
||||||
|
'getMyOverdueTasks',
|
||||||
);
|
);
|
||||||
|
|
||||||
private $both_allowed_procedures = array(
|
private $both_allowed_procedures = array(
|
||||||
|
@ -37,6 +39,8 @@ abstract class Base extends \Core\Base
|
||||||
'createTask',
|
'createTask',
|
||||||
'updateTask',
|
'updateTask',
|
||||||
'getBoard',
|
'getBoard',
|
||||||
|
'getProjectActivity',
|
||||||
|
'getOverdueTasksByProject',
|
||||||
);
|
);
|
||||||
|
|
||||||
public function checkProcedurePermission($is_user, $procedure)
|
public function checkProcedurePermission($is_user, $procedure)
|
||||||
|
@ -50,6 +54,8 @@ abstract class Base extends \Core\Base
|
||||||
else if (! $is_user && ! $is_both_procedure && $is_user_procedure) {
|
else if (! $is_user && ! $is_both_procedure && $is_user_procedure) {
|
||||||
throw new AccessDeniedException('Permission denied');
|
throw new AccessDeniedException('Permission denied');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->logger->debug('API call: '.$procedure);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function checkProjectPermission($project_id)
|
public function checkProjectPermission($project_id)
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
namespace Api;
|
namespace Api;
|
||||||
|
|
||||||
|
use Core\ObjectStorage\ObjectStorageException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* File API controller
|
* File API controller
|
||||||
*
|
*
|
||||||
|
@ -22,16 +24,17 @@ class File extends \Core\Base
|
||||||
|
|
||||||
public function downloadFile($file_id)
|
public function downloadFile($file_id)
|
||||||
{
|
{
|
||||||
$file = $this->file->getById($file_id);
|
try {
|
||||||
|
|
||||||
if (! empty($file)) {
|
$file = $this->file->getById($file_id);
|
||||||
|
|
||||||
$filename = FILES_DIR.$file['path'];
|
if (! empty($file)) {
|
||||||
|
return base64_encode($this->objectStorage->get($file['path']));
|
||||||
if (file_exists($filename)) {
|
|
||||||
return base64_encode(file_get_contents($filename));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (ObjectStorageException $e) {
|
||||||
|
$this->logger->error($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,8 @@ class Me extends Base
|
||||||
|
|
||||||
public function getMyActivityStream()
|
public function getMyActivityStream()
|
||||||
{
|
{
|
||||||
return $this->projectActivity->getProjects($this->projectPermission->getActiveMemberProjectIds($this->userSession->getId()), 100);
|
$project_ids = $this->projectPermission->getActiveMemberProjectIds($this->userSession->getId());
|
||||||
|
return $this->projectActivity->getProjects($project_ids, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createMyPrivateProject($name, $description = null)
|
public function createMyPrivateProject($name, $description = null)
|
||||||
|
@ -52,4 +53,17 @@ class Me extends Base
|
||||||
{
|
{
|
||||||
return $this->projectPermission->getMemberProjects($this->userSession->getId());
|
return $this->projectPermission->getMemberProjects($this->userSession->getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getMyOverdueTasks()
|
||||||
|
{
|
||||||
|
return $this->taskFinder->getOverdueTasksByUser($this->userSession->getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMyProjects()
|
||||||
|
{
|
||||||
|
$project_ids = $this->projectPermission->getActiveMemberProjectIds($this->userSession->getId());
|
||||||
|
$projects = $this->project->getAllByIds($project_ids);
|
||||||
|
|
||||||
|
return $this->formatProjects($projects);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,6 +58,7 @@ class Project extends Base
|
||||||
|
|
||||||
public function getProjectActivity($project_id)
|
public function getProjectActivity($project_id)
|
||||||
{
|
{
|
||||||
|
$this->checkProjectPermission($project_id);
|
||||||
return $this->projectActivity->getProject($project_id);
|
return $this->projectActivity->getProject($project_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,14 +40,18 @@ class Swimlane extends \Core\Base
|
||||||
return $this->swimlane->getDefault($project_id);
|
return $this->swimlane->getDefault($project_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addSwimlane($project_id, $name)
|
public function addSwimlane($project_id, $name, $description = '')
|
||||||
{
|
{
|
||||||
return $this->swimlane->create($project_id, $name);
|
return $this->swimlane->create(array('project_id' => $project_id, 'name' => $name, 'description' => $description));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function updateSwimlane($swimlane_id, $name)
|
public function updateSwimlane($swimlane_id, $name, $description = null)
|
||||||
{
|
{
|
||||||
return $this->swimlane->rename($swimlane_id, $name);
|
$values = array('id' => $swimlane_id, 'name' => $name);
|
||||||
|
if (!is_null($description)) {
|
||||||
|
$values['description'] = $description;
|
||||||
|
}
|
||||||
|
return $this->swimlane->update($values);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function removeSwimlane($project_id, $swimlane_id)
|
public function removeSwimlane($project_id, $swimlane_id)
|
||||||
|
|
|
@ -34,6 +34,12 @@ class Task extends Base
|
||||||
{
|
{
|
||||||
return $this->taskFinder->getOverdueTasks();
|
return $this->taskFinder->getOverdueTasks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getOverdueTasksByProject($project_id)
|
||||||
|
{
|
||||||
|
$this->checkProjectPermission($project_id);
|
||||||
|
return $this->taskFinder->getOverdueTasksByProject($project_id);
|
||||||
|
}
|
||||||
|
|
||||||
public function openTask($task_id)
|
public function openTask($task_id)
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,6 +19,190 @@ class Ldap extends Base
|
||||||
*/
|
*/
|
||||||
const AUTH_NAME = 'LDAP';
|
const AUTH_NAME = 'LDAP';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get LDAP server name
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getLdapServer()
|
||||||
|
{
|
||||||
|
return LDAP_SERVER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get LDAP bind type
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public function getLdapBindType()
|
||||||
|
{
|
||||||
|
return LDAP_BIND_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get LDAP server port
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public function getLdapPort()
|
||||||
|
{
|
||||||
|
return LDAP_PORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get LDAP username (proxy auth)
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getLdapUsername()
|
||||||
|
{
|
||||||
|
return LDAP_USERNAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get LDAP password (proxy auth)
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getLdapPassword()
|
||||||
|
{
|
||||||
|
return LDAP_PASSWORD;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get LDAP Base DN
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getLdapBaseDn()
|
||||||
|
{
|
||||||
|
return LDAP_ACCOUNT_BASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get LDAP account id attribute
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getLdapAccountId()
|
||||||
|
{
|
||||||
|
return LDAP_ACCOUNT_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get LDAP account email attribute
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getLdapAccountEmail()
|
||||||
|
{
|
||||||
|
return LDAP_ACCOUNT_EMAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get LDAP account name attribute
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getLdapAccountName()
|
||||||
|
{
|
||||||
|
return LDAP_ACCOUNT_FULLNAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get LDAP account memberof attribute
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getLdapAccountMemberOf()
|
||||||
|
{
|
||||||
|
return LDAP_ACCOUNT_MEMBEROF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get LDAP admin group DN
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getLdapGroupAdmin()
|
||||||
|
{
|
||||||
|
return LDAP_GROUP_ADMIN_DN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get LDAP project admin group DN
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getLdapGroupProjectAdmin()
|
||||||
|
{
|
||||||
|
return LDAP_GROUP_PROJECT_ADMIN_DN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get LDAP username pattern
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $username
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getLdapUserPattern($username)
|
||||||
|
{
|
||||||
|
return sprintf(LDAP_USER_PATTERN, $username);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the LDAP username is case sensitive
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function isLdapAccountCaseSensitive()
|
||||||
|
{
|
||||||
|
return LDAP_USERNAME_CASE_SENSITIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the automatic account creation is enabled
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function isLdapAccountCreationEnabled()
|
||||||
|
{
|
||||||
|
return LDAP_ACCOUNT_CREATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ge the list of attributes to fetch when reading the LDAP user entry
|
||||||
|
*
|
||||||
|
* Must returns array with index that start at 0 otherwise ldap_search returns a warning "Array initialization wrong"
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getProfileAttributes()
|
||||||
|
{
|
||||||
|
return array_values(array_filter(array(
|
||||||
|
$this->getLdapAccountId(),
|
||||||
|
$this->getLdapAccountName(),
|
||||||
|
$this->getLdapAccountEmail(),
|
||||||
|
$this->getLdapAccountMemberOf()
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authenticate the user
|
* Authenticate the user
|
||||||
*
|
*
|
||||||
|
@ -29,7 +213,7 @@ class Ldap extends Base
|
||||||
*/
|
*/
|
||||||
public function authenticate($username, $password)
|
public function authenticate($username, $password)
|
||||||
{
|
{
|
||||||
$username = LDAP_USERNAME_CASE_SENSITIVE ? $username : strtolower($username);
|
$username = $this->isLdapAccountCaseSensitive() ? $username : strtolower($username);
|
||||||
$result = $this->findUser($username, $password);
|
$result = $this->findUser($username, $password);
|
||||||
|
|
||||||
if (is_array($result)) {
|
if (is_array($result)) {
|
||||||
|
@ -46,7 +230,7 @@ class Ldap extends Base
|
||||||
else {
|
else {
|
||||||
|
|
||||||
// We create automatically a new user
|
// We create automatically a new user
|
||||||
if (LDAP_ACCOUNT_CREATION && $this->createUser($username, $result['name'], $result['email'])) {
|
if ($this->isLdapAccountCreationEnabled() && $this->user->create($result) !== false) {
|
||||||
$user = $this->user->getByUsername($username);
|
$user = $this->user->getByUsername($username);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -64,28 +248,6 @@ class Ldap extends Base
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new local user after the LDAP authentication
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param string $username Username
|
|
||||||
* @param string $name Name of the user
|
|
||||||
* @param string $email Email address
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function createUser($username, $name, $email)
|
|
||||||
{
|
|
||||||
$values = array(
|
|
||||||
'username' => $username,
|
|
||||||
'name' => $name,
|
|
||||||
'email' => $email,
|
|
||||||
'is_admin' => 0,
|
|
||||||
'is_ldap_user' => 1,
|
|
||||||
);
|
|
||||||
|
|
||||||
return $this->user->create($values);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the user from the LDAP server
|
* Find the user from the LDAP server
|
||||||
*
|
*
|
||||||
|
@ -98,8 +260,8 @@ class Ldap extends Base
|
||||||
{
|
{
|
||||||
$ldap = $this->connect();
|
$ldap = $this->connect();
|
||||||
|
|
||||||
if (is_resource($ldap) && $this->bind($ldap, $username, $password)) {
|
if ($ldap !== false && $this->bind($ldap, $username, $password)) {
|
||||||
return $this->search($ldap, $username, $password);
|
return $this->getProfile($ldap, $username, $password);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -108,13 +270,14 @@ class Ldap extends Base
|
||||||
/**
|
/**
|
||||||
* LDAP connection
|
* LDAP connection
|
||||||
*
|
*
|
||||||
* @access private
|
* @access public
|
||||||
* @return resource $ldap LDAP connection
|
* @return resource|boolean
|
||||||
*/
|
*/
|
||||||
private function connect()
|
public function connect()
|
||||||
{
|
{
|
||||||
if (! function_exists('ldap_connect')) {
|
if (! function_exists('ldap_connect')) {
|
||||||
die('The PHP LDAP extension is required');
|
$this->logger->error('LDAP: The PHP LDAP extension is required');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip SSL certificate verification
|
// Skip SSL certificate verification
|
||||||
|
@ -122,10 +285,11 @@ class Ldap extends Base
|
||||||
putenv('LDAPTLS_REQCERT=never');
|
putenv('LDAPTLS_REQCERT=never');
|
||||||
}
|
}
|
||||||
|
|
||||||
$ldap = ldap_connect(LDAP_SERVER, LDAP_PORT);
|
$ldap = ldap_connect($this->getLdapServer(), $this->getLdapPort());
|
||||||
|
|
||||||
if (! is_resource($ldap)) {
|
if ($ldap === false) {
|
||||||
die('Unable to connect to the LDAP server: "'.LDAP_SERVER.'"');
|
$this->logger->error('LDAP: Unable to connect to the LDAP server');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
|
ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
|
||||||
|
@ -134,30 +298,31 @@ class Ldap extends Base
|
||||||
ldap_set_option($ldap, LDAP_OPT_TIMELIMIT, 1);
|
ldap_set_option($ldap, LDAP_OPT_TIMELIMIT, 1);
|
||||||
|
|
||||||
if (LDAP_START_TLS && ! @ldap_start_tls($ldap)) {
|
if (LDAP_START_TLS && ! @ldap_start_tls($ldap)) {
|
||||||
die('Unable to use ldap_start_tls()');
|
$this->logger->error('LDAP: Unable to use ldap_start_tls()');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ldap;
|
return $ldap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LDAP bind
|
* LDAP authentication
|
||||||
*
|
*
|
||||||
* @access private
|
* @access public
|
||||||
* @param resource $ldap LDAP connection
|
* @param resource $ldap
|
||||||
* @param string $username Username
|
* @param string $username
|
||||||
* @param string $password Password
|
* @param string $password
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
private function bind($ldap, $username, $password)
|
public function bind($ldap, $username, $password)
|
||||||
{
|
{
|
||||||
if (LDAP_BIND_TYPE === 'user') {
|
if ($this->getLdapBindType() === 'user') {
|
||||||
$ldap_username = sprintf(LDAP_USERNAME, $username);
|
$ldap_username = sprintf($this->getLdapUsername(), $username);
|
||||||
$ldap_password = $password;
|
$ldap_password = $password;
|
||||||
}
|
}
|
||||||
else if (LDAP_BIND_TYPE === 'proxy') {
|
else if ($this->getLdapBindType() === 'proxy') {
|
||||||
$ldap_username = LDAP_USERNAME;
|
$ldap_username = $this->getLdapUsername();
|
||||||
$ldap_password = LDAP_PASSWORD;
|
$ldap_password = $this->getLdapPassword();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$ldap_username = null;
|
$ldap_username = null;
|
||||||
|
@ -165,6 +330,8 @@ class Ldap extends Base
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! @ldap_bind($ldap, $ldap_username, $ldap_password)) {
|
if (! @ldap_bind($ldap, $ldap_username, $ldap_password)) {
|
||||||
|
$this->logger->error('LDAP: Unable to bind to server with: '.$ldap_username);
|
||||||
|
$this->logger->error('LDAP: bind type='.$this->getLdapBindType());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,118 +339,189 @@ class Ldap extends Base
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LDAP user lookup
|
* Get LDAP user profile
|
||||||
*
|
*
|
||||||
* @access private
|
* @access public
|
||||||
* @param resource $ldap LDAP connection
|
* @param resource $ldap
|
||||||
* @param string $username Username
|
* @param string $username
|
||||||
* @param string $password Password
|
* @param string $password
|
||||||
* @return boolean|array
|
* @return boolean|array
|
||||||
*/
|
*/
|
||||||
private function search($ldap, $username, $password)
|
public function getProfile($ldap, $username, $password)
|
||||||
{
|
{
|
||||||
$sr = @ldap_search($ldap, LDAP_ACCOUNT_BASE, sprintf(LDAP_USER_PATTERN, $username), array(LDAP_ACCOUNT_FULLNAME, LDAP_ACCOUNT_EMAIL));
|
$user_pattern = $this->getLdapUserPattern($username);
|
||||||
|
$entries = $this->executeQuery($ldap, $user_pattern);
|
||||||
|
|
||||||
if ($sr === false) {
|
if ($entries === false) {
|
||||||
|
$this->logger->error('LDAP: Unable to get user profile: '.$user_pattern);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$info = ldap_get_entries($ldap, $sr);
|
if (@ldap_bind($ldap, $entries[0]['dn'], $password)) {
|
||||||
|
return $this->prepareProfile($ldap, $entries, $username);
|
||||||
// User not found
|
|
||||||
if (count($info) == 0 || $info['count'] == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We got our user
|
if (DEBUG) {
|
||||||
if (@ldap_bind($ldap, $info[0]['dn'], $password)) {
|
$this->logger->debug('LDAP: wrong password for '.$entries[0]['dn']);
|
||||||
|
|
||||||
return array(
|
|
||||||
'username' => $username,
|
|
||||||
'name' => $this->getFromInfo($info, LDAP_ACCOUNT_FULLNAME),
|
|
||||||
'email' => $this->getFromInfo($info, LDAP_ACCOUNT_EMAIL),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve info on LDAP user
|
* Build user profile from LDAP information
|
||||||
*
|
*
|
||||||
* @param string $username Username
|
* @access public
|
||||||
* @param string $email Email address
|
* @param resource $ldap
|
||||||
|
* @param array $entries
|
||||||
|
* @param string $username
|
||||||
|
* @return boolean|array
|
||||||
*/
|
*/
|
||||||
public function lookup($username = null, $email = null)
|
public function prepareProfile($ldap, array $entries, $username)
|
||||||
{
|
{
|
||||||
$query = $this->getQuery($username, $email);
|
if ($this->getLdapAccountId() !== '') {
|
||||||
if ($query === false) {
|
$username = $this->getEntry($entries, $this->getLdapAccountId(), $username);
|
||||||
|
}
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'username' => $username,
|
||||||
|
'name' => $this->getEntry($entries, $this->getLdapAccountName()),
|
||||||
|
'email' => $this->getEntry($entries, $this->getLdapAccountEmail()),
|
||||||
|
'is_admin' => (int) $this->isMemberOf($this->getEntries($entries, $this->getLdapAccountMemberOf()), $this->getLdapGroupAdmin()),
|
||||||
|
'is_project_admin' => (int) $this->isMemberOf($this->getEntries($entries, $this->getLdapAccountMemberOf()), $this->getLdapGroupProjectAdmin()),
|
||||||
|
'is_ldap_user' => 1,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check group membership
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $group_entries
|
||||||
|
* @param string $group_dn
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function isMemberOf(array $group_entries, $group_dn)
|
||||||
|
{
|
||||||
|
if (! isset($group_entries['count']) || empty($group_dn)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect and attempt anonymous bind
|
for ($i = 0; $i < $group_entries['count']; $i++) {
|
||||||
|
if ($group_entries[$i] === $group_dn) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve info on LDAP user by username or email
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $username
|
||||||
|
* @param string $email
|
||||||
|
* @return boolean|array
|
||||||
|
*/
|
||||||
|
public function lookup($username = null, $email = null)
|
||||||
|
{
|
||||||
|
$query = $this->getLookupQuery($username, $email);
|
||||||
|
if ($query === '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect and attempt anonymous or proxy binding
|
||||||
$ldap = $this->connect();
|
$ldap = $this->connect();
|
||||||
if (! is_resource($ldap) || ! $this->bind($ldap, null, null)) {
|
if ($ldap === false || ! $this->bind($ldap, null, null)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to find user
|
// Try to find user
|
||||||
$sr = @ldap_search($ldap, LDAP_ACCOUNT_BASE, $query, array(LDAP_ACCOUNT_FULLNAME, LDAP_ACCOUNT_EMAIL, LDAP_ACCOUNT_ID));
|
$entries = $this->executeQuery($ldap, $query);
|
||||||
if ($sr === false) {
|
if ($entries === false) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$info = ldap_get_entries($ldap, $sr);
|
|
||||||
|
|
||||||
// User not found
|
|
||||||
if (count($info) == 0 || $info['count'] == 0) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// User id not retrieved: LDAP_ACCOUNT_ID not properly configured
|
// User id not retrieved: LDAP_ACCOUNT_ID not properly configured
|
||||||
if (empty($username) && ! isset($info[0][LDAP_ACCOUNT_ID][0])) {
|
if (empty($username) && ! isset($entries[0][$this->getLdapAccountId()][0])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return array(
|
return $this->prepareProfile($ldap, $entries, $username);
|
||||||
'username' => $this->getFromInfo($info, LDAP_ACCOUNT_ID, $username),
|
}
|
||||||
'name' => $this->getFromInfo($info, LDAP_ACCOUNT_FULLNAME),
|
|
||||||
'email' => $this->getFromInfo($info, LDAP_ACCOUNT_EMAIL, $email),
|
/**
|
||||||
);
|
* Execute LDAP query
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param resource $ldap
|
||||||
|
* @param string $query
|
||||||
|
* @return boolean|array
|
||||||
|
*/
|
||||||
|
private function executeQuery($ldap, $query)
|
||||||
|
{
|
||||||
|
$sr = @ldap_search($ldap, $this->getLdapBaseDn(), $query, $this->getProfileAttributes());
|
||||||
|
if ($sr === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$entries = ldap_get_entries($ldap, $sr);
|
||||||
|
if ($entries === false || count($entries) === 0 || $entries['count'] == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the LDAP query to find a user
|
* Get the LDAP query to find a user
|
||||||
*
|
*
|
||||||
* @param string $username Username
|
* @access private
|
||||||
* @param string $email Email address
|
* @param string $username
|
||||||
|
* @param string $email
|
||||||
|
* @return string
|
||||||
*/
|
*/
|
||||||
private function getQuery($username, $email)
|
private function getLookupQuery($username, $email)
|
||||||
{
|
{
|
||||||
if ($username && $email) {
|
if (! empty($username) && ! empty($email)) {
|
||||||
return '(&('.sprintf(LDAP_USER_PATTERN, $username).')('.LDAP_ACCOUNT_EMAIL.'='.$email.'))';
|
return '(&('.$this->getLdapUserPattern($username).')('.$this->getLdapAccountEmail().'='.$email.'))';
|
||||||
}
|
}
|
||||||
else if ($username) {
|
else if (! empty($username)) {
|
||||||
return sprintf(LDAP_USER_PATTERN, $username);
|
return $this->getLdapUserPattern($username);
|
||||||
}
|
}
|
||||||
else if ($email) {
|
else if (! empty($email)) {
|
||||||
return '('.LDAP_ACCOUNT_EMAIL.'='.$email.')';
|
return '('.$this->getLdapAccountEmail().'='.$email.')';
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a value from the LDAP info
|
* Return one entry from a list of entries
|
||||||
*
|
*
|
||||||
* @param array $info LDAP info
|
* @access private
|
||||||
* @param string $key Key
|
* @param array $entries LDAP entries
|
||||||
* @param string $default Default value if key not set in entry
|
* @param string $key Key
|
||||||
|
* @param string $default Default value if key not set in entry
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
private function getFromInfo($info, $key, $default = '')
|
private function getEntry(array $entries, $key, $default = '')
|
||||||
{
|
{
|
||||||
return isset($info[0][$key][0]) ? $info[0][$key][0] : $default;
|
return isset($entries[0][$key][0]) ? $entries[0][$key][0] : $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return subset of entries
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param array $entries
|
||||||
|
* @param string $key
|
||||||
|
* @param array $default
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function getEntries(array $entries, $key, $default = array())
|
||||||
|
{
|
||||||
|
return isset($entries[0][$key]) ? $entries[0][$key] : $default;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,6 @@ class ReverseProxy extends Base
|
||||||
public function authenticate()
|
public function authenticate()
|
||||||
{
|
{
|
||||||
if (isset($_SERVER[REVERSE_PROXY_USER_HEADER])) {
|
if (isset($_SERVER[REVERSE_PROXY_USER_HEADER])) {
|
||||||
|
|
||||||
$login = $_SERVER[REVERSE_PROXY_USER_HEADER];
|
$login = $_SERVER[REVERSE_PROXY_USER_HEADER];
|
||||||
$user = $this->user->getByUsername($login);
|
$user = $this->user->getByUsername($login);
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ class TaskOverdueNotification extends Base
|
||||||
|
|
||||||
protected function execute(InputInterface $input, OutputInterface $output)
|
protected function execute(InputInterface $input, OutputInterface $output)
|
||||||
{
|
{
|
||||||
$tasks = $this->notification->sendOverdueTaskNotifications();
|
$tasks = $this->overdueNotification->sendOverdueTaskNotifications();
|
||||||
|
|
||||||
if ($input->getOption('show')) {
|
if ($input->getOption('show')) {
|
||||||
$this->showTable($output, $tasks);
|
$this->showTable($output, $tasks);
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
namespace Controller;
|
namespace Controller;
|
||||||
|
|
||||||
use Model\Subtask as SubtaskModel;
|
use Model\Subtask as SubtaskModel;
|
||||||
use Model\Task as TaskModel;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Application controller
|
* Application controller
|
||||||
|
@ -188,6 +187,22 @@ class App extends Base
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* My notifications
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function notifications()
|
||||||
|
{
|
||||||
|
$user = $this->getUser();
|
||||||
|
|
||||||
|
$this->response->html($this->layout('app/notifications', array(
|
||||||
|
'title' => t('My notifications'),
|
||||||
|
'notifications' => $this->webNotification->getAll($user['id']),
|
||||||
|
'user' => $user,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render Markdown text and reply with the HTML Code
|
* Render Markdown text and reply with the HTML Code
|
||||||
*
|
*
|
||||||
|
@ -213,7 +228,7 @@ class App extends Base
|
||||||
{
|
{
|
||||||
$search = $this->request->getStringParam('term');
|
$search = $this->request->getStringParam('term');
|
||||||
|
|
||||||
$filter = $this->taskFilter
|
$filter = $this->taskFilterAutoCompleteFormatter
|
||||||
->create()
|
->create()
|
||||||
->filterByProjects($this->projectPermission->getActiveMemberProjectIds($this->userSession->getId()))
|
->filterByProjects($this->projectPermission->getActiveMemberProjectIds($this->userSession->getId()))
|
||||||
->excludeTasks(array($this->request->getIntegerParam('exclude_task_id')));
|
->excludeTasks(array($this->request->getIntegerParam('exclude_task_id')));
|
||||||
|
@ -226,6 +241,6 @@ class App extends Base
|
||||||
$filter->filterByTitle($search);
|
$filter->filterByTitle($search);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->json($filter->toAutoCompletion());
|
$this->response->json($filter->format());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,7 @@ abstract class Base extends \Core\Base
|
||||||
private function sendHeaders($action)
|
private function sendHeaders($action)
|
||||||
{
|
{
|
||||||
// HTTP secure headers
|
// HTTP secure headers
|
||||||
$this->response->csp(array('style-src' => "'self' 'unsafe-inline'", 'img-src' => '* data:'));
|
$this->response->csp($this->container['cspRules']);
|
||||||
$this->response->nosniff();
|
$this->response->nosniff();
|
||||||
$this->response->xss();
|
$this->response->xss();
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ class Board extends Base
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display the board with a specific layout
|
// Display the board with a specific layout
|
||||||
$this->response->html($this->template->layout('board/public_view', array(
|
$this->response->html($this->template->layout('board/view_public', array(
|
||||||
'project' => $project,
|
'project' => $project,
|
||||||
'swimlanes' => $this->board->getBoard($project['id']),
|
'swimlanes' => $this->board->getBoard($project['id']),
|
||||||
'title' => $project['name'],
|
'title' => $project['name'],
|
||||||
|
@ -49,9 +49,10 @@ class Board extends Base
|
||||||
{
|
{
|
||||||
$params = $this->getProjectFilters('board', 'show');
|
$params = $this->getProjectFilters('board', 'show');
|
||||||
|
|
||||||
$this->response->html($this->template->layout('board/private_view', array(
|
$this->response->html($this->template->layout('board/view_private', array(
|
||||||
'categories_list' => $this->category->getList($params['project']['id'], false),
|
'categories_list' => $this->category->getList($params['project']['id'], false),
|
||||||
'users_list' => $this->projectPermission->getMemberList($params['project']['id'], false),
|
'users_list' => $this->projectPermission->getMemberList($params['project']['id'], false),
|
||||||
|
'custom_filters_list' => $this->customFilter->getAll($params['project']['id'], $this->userSession->getId()),
|
||||||
'swimlanes' => $this->taskFilter->search($params['filters']['search'])->getBoard($params['project']['id']),
|
'swimlanes' => $this->taskFilter->search($params['filters']['search'])->getBoard($params['project']['id']),
|
||||||
'description' => $params['project']['description'],
|
'description' => $params['project']['description'],
|
||||||
'board_private_refresh_interval' => $this->config->get('board_private_refresh_interval'),
|
'board_private_refresh_interval' => $this->config->get('board_private_refresh_interval'),
|
||||||
|
@ -136,7 +137,7 @@ class Board extends Base
|
||||||
}
|
}
|
||||||
|
|
||||||
$values = $this->request->getJson();
|
$values = $this->request->getJson();
|
||||||
$this->userSession->setFilters($project_id, $values['search']);
|
$this->userSession->setFilters($project_id, empty($values['search']) ? '' : $values['search']);
|
||||||
|
|
||||||
$this->response->html($this->renderBoard($project_id));
|
$this->response->html($this->renderBoard($project_id));
|
||||||
}
|
}
|
||||||
|
@ -320,6 +321,18 @@ class Board extends Base
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display swimlane description in tooltip
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function swimlane()
|
||||||
|
{
|
||||||
|
$this->getProject();
|
||||||
|
$swimlane = $this->swimlane->getById($this->request->getIntegerParam('swimlane_id'));
|
||||||
|
$this->response->html($this->template->render('board/tooltip_description', array('task' => $swimlane)));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable collapsed mode
|
* Enable collapsed mode
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,135 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Controller;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Budget
|
|
||||||
*
|
|
||||||
* @package controller
|
|
||||||
* @author Frederic Guillot
|
|
||||||
*/
|
|
||||||
class Budget extends Base
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Budget index page
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function index()
|
|
||||||
{
|
|
||||||
$project = $this->getProject();
|
|
||||||
|
|
||||||
$this->response->html($this->projectLayout('budget/index', array(
|
|
||||||
'daily_budget' => $this->budget->getDailyBudgetBreakdown($project['id']),
|
|
||||||
'project' => $project,
|
|
||||||
'title' => t('Budget')
|
|
||||||
), 'budget/sidebar'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cost breakdown by users/subtasks/tasks
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function breakdown()
|
|
||||||
{
|
|
||||||
$project = $this->getProject();
|
|
||||||
|
|
||||||
$paginator = $this->paginator
|
|
||||||
->setUrl('budget', 'breakdown', array('project_id' => $project['id']))
|
|
||||||
->setMax(30)
|
|
||||||
->setOrder('start')
|
|
||||||
->setDirection('DESC')
|
|
||||||
->setQuery($this->budget->getSubtaskBreakdown($project['id']))
|
|
||||||
->calculate();
|
|
||||||
|
|
||||||
$this->response->html($this->projectLayout('budget/breakdown', array(
|
|
||||||
'paginator' => $paginator,
|
|
||||||
'project' => $project,
|
|
||||||
'title' => t('Budget')
|
|
||||||
), 'budget/sidebar'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create budget lines
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function create(array $values = array(), array $errors = array())
|
|
||||||
{
|
|
||||||
$project = $this->getProject();
|
|
||||||
|
|
||||||
if (empty($values)) {
|
|
||||||
$values['date'] = date('Y-m-d');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->response->html($this->projectLayout('budget/create', array(
|
|
||||||
'lines' => $this->budget->getAll($project['id']),
|
|
||||||
'values' => $values + array('project_id' => $project['id']),
|
|
||||||
'errors' => $errors,
|
|
||||||
'project' => $project,
|
|
||||||
'title' => t('Budget lines')
|
|
||||||
), 'budget/sidebar'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate and save a new budget
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function save()
|
|
||||||
{
|
|
||||||
$project = $this->getProject();
|
|
||||||
|
|
||||||
$values = $this->request->getValues();
|
|
||||||
list($valid, $errors) = $this->budget->validateCreation($values);
|
|
||||||
|
|
||||||
if ($valid) {
|
|
||||||
|
|
||||||
if ($this->budget->create($values['project_id'], $values['amount'], $values['comment'], $values['date'])) {
|
|
||||||
$this->session->flash(t('The budget line have been created successfully.'));
|
|
||||||
$this->response->redirect($this->helper->url->to('budget', 'create', array('project_id' => $project['id'])));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$this->session->flashError(t('Unable to create the budget line.'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->create($values, $errors);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Confirmation dialog before removing a budget
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function confirm()
|
|
||||||
{
|
|
||||||
$project = $this->getProject();
|
|
||||||
|
|
||||||
$this->response->html($this->projectLayout('budget/remove', array(
|
|
||||||
'project' => $project,
|
|
||||||
'budget_id' => $this->request->getIntegerParam('budget_id'),
|
|
||||||
'title' => t('Remove a budget line'),
|
|
||||||
), 'budget/sidebar'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a budget
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function remove()
|
|
||||||
{
|
|
||||||
$this->checkCSRFParam();
|
|
||||||
$project = $this->getProject();
|
|
||||||
|
|
||||||
if ($this->budget->remove($this->request->getIntegerParam('budget_id'))) {
|
|
||||||
$this->session->flash(t('Budget line removed successfully.'));
|
|
||||||
} else {
|
|
||||||
$this->session->flashError(t('Unable to remove this budget line.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('budget', 'create', array('project_id' => $project['id'])));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -37,20 +37,26 @@ class Calendar extends Base
|
||||||
$end = $this->request->getStringParam('end');
|
$end = $this->request->getStringParam('end');
|
||||||
|
|
||||||
// Common filter
|
// Common filter
|
||||||
$filter = $this->taskFilter
|
$filter = $this->taskFilterCalendarFormatter
|
||||||
->search($this->userSession->getFilters($project_id))
|
->search($this->userSession->getFilters($project_id))
|
||||||
->filterByProject($project_id);
|
->filterByProject($project_id);
|
||||||
|
|
||||||
// Tasks
|
// Tasks
|
||||||
if ($this->config->get('calendar_project_tasks', 'date_started') === 'date_creation') {
|
if ($this->config->get('calendar_project_tasks', 'date_started') === 'date_creation') {
|
||||||
$events = $filter->copy()->filterByCreationDateRange($start, $end)->toDateTimeCalendarEvents('date_creation', 'date_completed');
|
$events = $filter->copy()->filterByCreationDateRange($start, $end)->setColumns('date_creation', 'date_completed')->format();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$events = $filter->copy()->filterByStartDateRange($start, $end)->toDateTimeCalendarEvents('date_started', 'date_completed');
|
$events = $filter->copy()->filterByStartDateRange($start, $end)->setColumns('date_started', 'date_completed')->format();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tasks with due date
|
// Tasks with due date
|
||||||
$events = array_merge($events, $filter->copy()->filterByDueDateRange($start, $end)->toAllDayCalendarEvents());
|
$events = array_merge($events, $filter->copy()->filterByDueDateRange($start, $end)->setColumns('date_due')->setFullDay()->format());
|
||||||
|
|
||||||
|
$events = $this->hook->merge('controller:calendar:project:events', $events, array(
|
||||||
|
'project_id' => $project_id,
|
||||||
|
'start' => $start,
|
||||||
|
'end' => $end,
|
||||||
|
));
|
||||||
|
|
||||||
$this->response->json($events);
|
$this->response->json($events);
|
||||||
}
|
}
|
||||||
|
@ -65,17 +71,17 @@ class Calendar extends Base
|
||||||
$user_id = $this->request->getIntegerParam('user_id');
|
$user_id = $this->request->getIntegerParam('user_id');
|
||||||
$start = $this->request->getStringParam('start');
|
$start = $this->request->getStringParam('start');
|
||||||
$end = $this->request->getStringParam('end');
|
$end = $this->request->getStringParam('end');
|
||||||
$filter = $this->taskFilter->create()->filterByOwner($user_id)->filterByStatus(TaskModel::STATUS_OPEN);
|
$filter = $this->taskFilterCalendarFormatter->create()->filterByOwner($user_id)->filterByStatus(TaskModel::STATUS_OPEN);
|
||||||
|
|
||||||
// Task with due date
|
// Task with due date
|
||||||
$events = $filter->copy()->filterByDueDateRange($start, $end)->toAllDayCalendarEvents();
|
$events = $filter->copy()->filterByDueDateRange($start, $end)->setColumns('date_due')->setFullDay()->format();
|
||||||
|
|
||||||
// Tasks
|
// Tasks
|
||||||
if ($this->config->get('calendar_user_tasks', 'date_started') === 'date_creation') {
|
if ($this->config->get('calendar_user_tasks', 'date_started') === 'date_creation') {
|
||||||
$events = array_merge($events, $filter->copy()->filterByCreationDateRange($start, $end)->toDateTimeCalendarEvents('date_creation', 'date_completed'));
|
$events = array_merge($events, $filter->copy()->filterByCreationDateRange($start, $end)->setColumns('date_creation', 'date_completed')->format());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$events = array_merge($events, $filter->copy()->filterByStartDateRange($start, $end)->toDateTimeCalendarEvents('date_started', 'date_completed'));
|
$events = array_merge($events, $filter->copy()->filterByStartDateRange($start, $end)->setColumns('date_started', 'date_completed')->format());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Subtasks time tracking
|
// Subtasks time tracking
|
||||||
|
@ -83,10 +89,11 @@ class Calendar extends Base
|
||||||
$events = array_merge($events, $this->subtaskTimeTracking->getUserCalendarEvents($user_id, $start, $end));
|
$events = array_merge($events, $this->subtaskTimeTracking->getUserCalendarEvents($user_id, $start, $end));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Subtask estimates
|
$events = $this->hook->merge('controller:calendar:user:events', $events, array(
|
||||||
if ($this->config->get('calendar_user_subtasks_forecast') == 1) {
|
'user_id' => $user_id,
|
||||||
$events = array_merge($events, $this->subtaskForecast->getCalendarEvents($user_id, $end));
|
'start' => $start,
|
||||||
}
|
'end' => $end,
|
||||||
|
));
|
||||||
|
|
||||||
$this->response->json($events);
|
$this->response->json($events);
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ class Config extends Base
|
||||||
$values += array('integration_slack_webhook' => 0, 'integration_hipchat' => 0, 'integration_gravatar' => 0, 'integration_jabber' => 0);
|
$values += array('integration_slack_webhook' => 0, 'integration_hipchat' => 0, 'integration_gravatar' => 0, 'integration_jabber' => 0);
|
||||||
break;
|
break;
|
||||||
case 'calendar':
|
case 'calendar':
|
||||||
$values += array('calendar_user_subtasks_forecast' => 0, 'calendar_user_subtasks_time_tracking' => 0);
|
$values += array('calendar_user_subtasks_time_tracking' => 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,6 +77,19 @@ class Config extends Base
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the plugin page
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function plugins()
|
||||||
|
{
|
||||||
|
$this->response->html($this->layout('config/plugins', array(
|
||||||
|
'plugins' => $this->pluginLoader->plugins,
|
||||||
|
'title' => t('Settings').' > '.t('Plugins'),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display the application settings page
|
* Display the application settings page
|
||||||
*
|
*
|
||||||
|
|
142
sources/app/Controller/Customfilter.php
Normal file
142
sources/app/Controller/Customfilter.php
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Controller;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom Filter management
|
||||||
|
*
|
||||||
|
* @package controller
|
||||||
|
* @author Timo Litzbarski
|
||||||
|
*/
|
||||||
|
class Customfilter extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display list of filters
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function index(array $values = array(), array $errors = array())
|
||||||
|
{
|
||||||
|
$project = $this->getProject();
|
||||||
|
|
||||||
|
$this->response->html($this->projectLayout('custom_filter/index', array(
|
||||||
|
'values' => $values + array('project_id' => $project['id']),
|
||||||
|
'errors' => $errors,
|
||||||
|
'project' => $project,
|
||||||
|
'custom_filters' => $this->customFilter->getAll($project['id'], $this->userSession->getId()),
|
||||||
|
'title' => t('Custom filters'),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save a new custom filter
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function save()
|
||||||
|
{
|
||||||
|
$project = $this->getProject();
|
||||||
|
|
||||||
|
$values = $this->request->getValues();
|
||||||
|
$values['user_id'] = $this->userSession->getId();
|
||||||
|
|
||||||
|
list($valid, $errors) = $this->customFilter->validateCreation($values);
|
||||||
|
|
||||||
|
if ($valid) {
|
||||||
|
if ($this->customFilter->create($values)) {
|
||||||
|
$this->session->flash(t('Your custom filter have been created successfully.'));
|
||||||
|
$this->response->redirect($this->helper->url->to('customfilter', 'index', array('project_id' => $project['id'])));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->session->flashError(t('Unable to create your custom filter.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->index($values, $errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a custom filter
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function remove()
|
||||||
|
{
|
||||||
|
$this->checkCSRFParam();
|
||||||
|
$project = $this->getProject();
|
||||||
|
$filter = $this->customFilter->getById($this->request->getIntegerParam('filter_id'));
|
||||||
|
|
||||||
|
$this->checkPermission($project, $filter);
|
||||||
|
|
||||||
|
if ($this->customFilter->remove($filter['id'])) {
|
||||||
|
$this->session->flash(t('Custom filter removed successfully.'));
|
||||||
|
} else {
|
||||||
|
$this->session->flashError(t('Unable to remove this custom filter.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->redirect($this->helper->url->to('customfilter', 'index', array('project_id' => $project['id'])));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Edit a custom filter (display the form)
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function edit(array $values = array(), array $errors = array())
|
||||||
|
{
|
||||||
|
$project = $this->getProject();
|
||||||
|
$filter = $this->customFilter->getById($this->request->getIntegerParam('filter_id'));
|
||||||
|
|
||||||
|
$this->checkPermission($project, $filter);
|
||||||
|
|
||||||
|
$this->response->html($this->projectLayout('custom_filter/edit', array(
|
||||||
|
'values' => empty($values) ? $filter : $values,
|
||||||
|
'errors' => $errors,
|
||||||
|
'project' => $project,
|
||||||
|
'filter' => $filter,
|
||||||
|
'title' => t('Edit custom filter')
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Edit a custom filter (validate the form and update the database)
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function update()
|
||||||
|
{
|
||||||
|
$project = $this->getProject();
|
||||||
|
$filter = $this->customFilter->getById($this->request->getIntegerParam('filter_id'));
|
||||||
|
|
||||||
|
$this->checkPermission($project, $filter);
|
||||||
|
|
||||||
|
$values = $this->request->getValues();
|
||||||
|
|
||||||
|
if (! isset($values['is_shared'])) {
|
||||||
|
$values += array('is_shared' => 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
list($valid, $errors) = $this->customFilter->validateModification($values);
|
||||||
|
|
||||||
|
if ($valid) {
|
||||||
|
if ($this->customFilter->update($values)) {
|
||||||
|
$this->session->flash(t('Your custom filter have been updated successfully.'));
|
||||||
|
$this->response->redirect($this->helper->url->to('customfilter', 'index', array('project_id' => $project['id'])));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->session->flashError(t('Unable to update custom filter.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->edit($values, $errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function checkPermission(array $project, array $filter)
|
||||||
|
{
|
||||||
|
$user_id = $this->userSession->getId();
|
||||||
|
|
||||||
|
if ($filter['user_id'] != $user_id && (! $this->projectPermission->isManager($project['id'], $user_id) || ! $this->userSession->isAdmin())) {
|
||||||
|
$this->forbidden();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,7 +16,7 @@ class Doc extends Base
|
||||||
{
|
{
|
||||||
$url = $this->helper->url;
|
$url = $this->helper->url;
|
||||||
$data = file_get_contents($filename);
|
$data = file_get_contents($filename);
|
||||||
list($title,, $content) = explode("\n", $data, 3);
|
list($title,) = explode("\n", $data, 2);
|
||||||
|
|
||||||
$replaceUrl = function (array $matches) use ($url) {
|
$replaceUrl = function (array $matches) use ($url) {
|
||||||
return '('.$url->to('doc', 'show', array('file' => str_replace('.markdown', '', $matches[1]))).')';
|
return '('.$url->to('doc', 'show', array('file' => str_replace('.markdown', '', $matches[1]))).')';
|
||||||
|
@ -32,16 +32,24 @@ class Doc extends Base
|
||||||
|
|
||||||
public function show()
|
public function show()
|
||||||
{
|
{
|
||||||
$filename = $this->request->getStringParam('file', 'index');
|
$page = $this->request->getStringParam('file', 'index');
|
||||||
|
|
||||||
if (! preg_match('/^[a-z0-9\-]+/', $filename)) {
|
if (! preg_match('/^[a-z0-9\-]+/', $page)) {
|
||||||
$filename = 'index';
|
$page = 'index';
|
||||||
}
|
}
|
||||||
|
|
||||||
$filename = __DIR__.'/../../doc/'.$filename.'.markdown';
|
$filenames = array(__DIR__.'/../../doc/'.$page.'.markdown');
|
||||||
|
$filename = __DIR__.'/../../doc/index.markdown';
|
||||||
|
|
||||||
if (! file_exists($filename)) {
|
if ($this->config->getCurrentLanguage() === 'fr_FR') {
|
||||||
$filename = __DIR__.'/../../doc/index.markdown';
|
array_unshift($filenames, __DIR__.'/../../doc/fr/'.$page.'.markdown');
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($filenames as $file) {
|
||||||
|
if (file_exists($file)) {
|
||||||
|
$filename = $file;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->html($this->template->layout('doc/show', $this->readFile($filename) + array(
|
$this->response->html($this->template->layout('doc/show', $this->readFile($filename) + array(
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
namespace Controller;
|
namespace Controller;
|
||||||
|
|
||||||
|
use Core\ObjectStorage\ObjectStorageException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* File controller
|
* File controller
|
||||||
*
|
*
|
||||||
|
@ -60,7 +62,7 @@ class File extends Base
|
||||||
{
|
{
|
||||||
$task = $this->getTask();
|
$task = $this->getTask();
|
||||||
|
|
||||||
if (! $this->file->upload($task['project_id'], $task['id'], 'files')) {
|
if (! $this->file->uploadFiles($task['project_id'], $task['id'], 'files')) {
|
||||||
$this->session->flashError(t('Unable to upload the file.'));
|
$this->session->flashError(t('Unable to upload the file.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,16 +76,21 @@ class File extends Base
|
||||||
*/
|
*/
|
||||||
public function download()
|
public function download()
|
||||||
{
|
{
|
||||||
$task = $this->getTask();
|
try {
|
||||||
$file = $this->file->getById($this->request->getIntegerParam('file_id'));
|
|
||||||
$filename = FILES_DIR.$file['path'];
|
$task = $this->getTask();
|
||||||
|
$file = $this->file->getById($this->request->getIntegerParam('file_id'));
|
||||||
|
|
||||||
|
if ($file['task_id'] != $task['id']) {
|
||||||
|
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
|
||||||
|
}
|
||||||
|
|
||||||
if ($file['task_id'] == $task['id'] && file_exists($filename)) {
|
|
||||||
$this->response->forceDownload($file['name']);
|
$this->response->forceDownload($file['name']);
|
||||||
$this->response->binary(file_get_contents($filename));
|
$this->objectStorage->output($file['path']);
|
||||||
|
}
|
||||||
|
catch (ObjectStorageException $e) {
|
||||||
|
$this->logger->error($e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -111,17 +118,20 @@ class File extends Base
|
||||||
*/
|
*/
|
||||||
public function image()
|
public function image()
|
||||||
{
|
{
|
||||||
$task = $this->getTask();
|
try {
|
||||||
$file = $this->file->getById($this->request->getIntegerParam('file_id'));
|
|
||||||
$filename = FILES_DIR.$file['path'];
|
|
||||||
|
|
||||||
if ($file['task_id'] == $task['id'] && file_exists($filename)) {
|
$task = $this->getTask();
|
||||||
$metadata = getimagesize($filename);
|
$file = $this->file->getById($this->request->getIntegerParam('file_id'));
|
||||||
|
|
||||||
if (isset($metadata['mime'])) {
|
if ($file['task_id'] != $task['id']) {
|
||||||
$this->response->contentType($metadata['mime']);
|
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
|
||||||
readfile($filename);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->response->contentType($this->file->getImageMimeType($file['name']));
|
||||||
|
$this->objectStorage->output($file['path']);
|
||||||
|
}
|
||||||
|
catch (ObjectStorageException $e) {
|
||||||
|
$this->logger->error($e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,18 +142,20 @@ class File extends Base
|
||||||
*/
|
*/
|
||||||
public function thumbnail()
|
public function thumbnail()
|
||||||
{
|
{
|
||||||
$task = $this->getTask();
|
try {
|
||||||
$file = $this->file->getById($this->request->getIntegerParam('file_id'));
|
|
||||||
$filename = FILES_DIR.$file['path'];
|
|
||||||
|
|
||||||
if ($file['task_id'] == $task['id'] && file_exists($filename)) {
|
$task = $this->getTask();
|
||||||
|
$file = $this->file->getById($this->request->getIntegerParam('file_id'));
|
||||||
|
|
||||||
|
if ($file['task_id'] != $task['id']) {
|
||||||
|
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
|
||||||
|
}
|
||||||
|
|
||||||
$this->response->contentType('image/jpeg');
|
$this->response->contentType('image/jpeg');
|
||||||
$this->file->generateThumbnail(
|
$this->objectStorage->output($this->file->getThumbnailPath($file['path']));
|
||||||
$filename,
|
}
|
||||||
$this->request->getIntegerParam('width'),
|
catch (ObjectStorageException $e) {
|
||||||
$this->request->getIntegerParam('height')
|
$this->logger->error($e->getMessage());
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ class Gantt extends Base
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->html($this->template->layout('gantt/projects', array(
|
$this->response->html($this->template->layout('gantt/projects', array(
|
||||||
'projects' => $this->project->getGanttBars($project_ids),
|
'projects' => $this->projectGanttFormatter->filter($project_ids)->format(),
|
||||||
'title' => t('Gantt chart for all projects'),
|
'title' => t('Gantt chart for all projects'),
|
||||||
'board_selector' => $this->projectPermission->getAllowedProjects($this->userSession->getId()),
|
'board_selector' => $this->projectPermission->getAllowedProjects($this->userSession->getId()),
|
||||||
)));
|
)));
|
||||||
|
@ -57,7 +57,7 @@ class Gantt extends Base
|
||||||
public function project()
|
public function project()
|
||||||
{
|
{
|
||||||
$params = $this->getProjectFilters('gantt', 'project');
|
$params = $this->getProjectFilters('gantt', 'project');
|
||||||
$filter = $this->taskFilter->search($params['filters']['search'])->filterByProject($params['project']['id']);
|
$filter = $this->taskFilterGanttFormatter->search($params['filters']['search'])->filterByProject($params['project']['id']);
|
||||||
$sorting = $this->request->getStringParam('sorting', 'board');
|
$sorting = $this->request->getStringParam('sorting', 'board');
|
||||||
|
|
||||||
if ($sorting === 'date') {
|
if ($sorting === 'date') {
|
||||||
|
@ -70,7 +70,7 @@ class Gantt extends Base
|
||||||
$this->response->html($this->template->layout('gantt/project', $params + array(
|
$this->response->html($this->template->layout('gantt/project', $params + array(
|
||||||
'users_list' => $this->projectPermission->getMemberList($params['project']['id'], false),
|
'users_list' => $this->projectPermission->getMemberList($params['project']['id'], false),
|
||||||
'sorting' => $sorting,
|
'sorting' => $sorting,
|
||||||
'tasks' => $filter->toGanttBars(),
|
'tasks' => $filter->format(),
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,89 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Controller;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hourly Rate controller
|
|
||||||
*
|
|
||||||
* @package controller
|
|
||||||
* @author Frederic Guillot
|
|
||||||
*/
|
|
||||||
class Hourlyrate extends User
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Display rate and form
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function index(array $values = array(), array $errors = array())
|
|
||||||
{
|
|
||||||
$user = $this->getUser();
|
|
||||||
|
|
||||||
$this->response->html($this->layout('hourlyrate/index', array(
|
|
||||||
'rates' => $this->hourlyRate->getAllByUser($user['id']),
|
|
||||||
'currencies_list' => $this->config->getCurrencies(),
|
|
||||||
'values' => $values + array('user_id' => $user['id']),
|
|
||||||
'errors' => $errors,
|
|
||||||
'user' => $user,
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate and save a new rate
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function save()
|
|
||||||
{
|
|
||||||
$values = $this->request->getValues();
|
|
||||||
list($valid, $errors) = $this->hourlyRate->validateCreation($values);
|
|
||||||
|
|
||||||
if ($valid) {
|
|
||||||
|
|
||||||
if ($this->hourlyRate->create($values['user_id'], $values['rate'], $values['currency'], $values['date_effective'])) {
|
|
||||||
$this->session->flash(t('Hourly rate created successfully.'));
|
|
||||||
$this->response->redirect($this->helper->url->to('hourlyrate', 'index', array('user_id' => $values['user_id'])));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$this->session->flashError(t('Unable to save the hourly rate.'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->index($values, $errors);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Confirmation dialag box to remove a row
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function confirm()
|
|
||||||
{
|
|
||||||
$user = $this->getUser();
|
|
||||||
|
|
||||||
$this->response->html($this->layout('hourlyrate/remove', array(
|
|
||||||
'rate_id' => $this->request->getIntegerParam('rate_id'),
|
|
||||||
'user' => $user,
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a row
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function remove()
|
|
||||||
{
|
|
||||||
$this->checkCSRFParam();
|
|
||||||
$user = $this->getUser();
|
|
||||||
|
|
||||||
if ($this->hourlyRate->remove($this->request->getIntegerParam('rate_id'))) {
|
|
||||||
$this->session->flash(t('Rate removed successfully.'));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$this->session->flash(t('Unable to remove this rate.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('hourlyrate', 'index', array('user_id' => $user['id'])));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -29,7 +29,7 @@ class Ical extends Base
|
||||||
}
|
}
|
||||||
|
|
||||||
// Common filter
|
// Common filter
|
||||||
$filter = $this->taskFilter
|
$filter = $this->taskFilterICalendarFormatter
|
||||||
->create()
|
->create()
|
||||||
->filterByOwner($user['id']);
|
->filterByOwner($user['id']);
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ class Ical extends Base
|
||||||
}
|
}
|
||||||
|
|
||||||
// Common filter
|
// Common filter
|
||||||
$filter = $this->taskFilter
|
$filter = $this->taskFilterICalendarFormatter
|
||||||
->create()
|
->create()
|
||||||
->filterByProject($project['id']);
|
->filterByProject($project['id']);
|
||||||
|
|
||||||
|
@ -83,16 +83,31 @@ class Ical extends Base
|
||||||
|
|
||||||
// Tasks
|
// Tasks
|
||||||
if ($this->config->get('calendar_project_tasks', 'date_started') === 'date_creation') {
|
if ($this->config->get('calendar_project_tasks', 'date_started') === 'date_creation') {
|
||||||
$filter->copy()->filterByCreationDateRange($start, $end)->addDateTimeIcalEvents('date_creation', 'date_completed', $calendar);
|
$filter
|
||||||
|
->copy()
|
||||||
|
->filterByCreationDateRange($start, $end)
|
||||||
|
->setColumns('date_creation', 'date_completed')
|
||||||
|
->setCalendar($calendar)
|
||||||
|
->addDateTimeEvents();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$filter->copy()->filterByStartDateRange($start, $end)->addDateTimeIcalEvents('date_started', 'date_completed', $calendar);
|
$filter
|
||||||
|
->copy()
|
||||||
|
->filterByStartDateRange($start, $end)
|
||||||
|
->setColumns('date_started', 'date_completed')
|
||||||
|
->setCalendar($calendar)
|
||||||
|
->addDateTimeEvents($calendar);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tasks with due date
|
// Tasks with due date
|
||||||
$filter->copy()->filterByDueDateRange($start, $end)->addAllDayIcalEvents('date_due', $calendar);
|
$filter
|
||||||
|
->copy()
|
||||||
|
->filterByDueDateRange($start, $end)
|
||||||
|
->setColumns('date_due')
|
||||||
|
->setCalendar($calendar)
|
||||||
|
->addFullDayEvents($calendar);
|
||||||
|
|
||||||
$this->response->contentType('text/calendar; charset=utf-8');
|
$this->response->contentType('text/calendar; charset=utf-8');
|
||||||
echo $calendar->render();
|
echo $filter->setCalendar($calendar)->format();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,13 +59,12 @@ class Swimlane extends Base
|
||||||
public function save()
|
public function save()
|
||||||
{
|
{
|
||||||
$project = $this->getProject();
|
$project = $this->getProject();
|
||||||
|
|
||||||
$values = $this->request->getValues();
|
$values = $this->request->getValues();
|
||||||
list($valid, $errors) = $this->swimlane->validateCreation($values);
|
list($valid, $errors) = $this->swimlane->validateCreation($values);
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
|
|
||||||
if ($this->swimlane->create($project['id'], $values['name'])) {
|
if ($this->swimlane->create($values)) {
|
||||||
$this->session->flash(t('Your swimlane have been created successfully.'));
|
$this->session->flash(t('Your swimlane have been created successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id'])));
|
$this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id'])));
|
||||||
}
|
}
|
||||||
|
@ -134,8 +133,7 @@ class Swimlane extends Base
|
||||||
list($valid, $errors) = $this->swimlane->validateModification($values);
|
list($valid, $errors) = $this->swimlane->validateModification($values);
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
|
if ($this->swimlane->update($values)) {
|
||||||
if ($this->swimlane->rename($values['id'], $values['name'])) {
|
|
||||||
$this->session->flash(t('Swimlane updated successfully.'));
|
$this->session->flash(t('Swimlane updated successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id'])));
|
$this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id'])));
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,25 +59,29 @@ class Taskcreation extends Base
|
||||||
|
|
||||||
list($valid, $errors) = $this->taskValidator->validateCreation($values);
|
list($valid, $errors) = $this->taskValidator->validateCreation($values);
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid && $this->taskCreation->create($values)) {
|
||||||
|
$this->session->flash(t('Task created successfully.'));
|
||||||
if ($this->taskCreation->create($values)) {
|
$this->afterSave($project, $values);
|
||||||
$this->session->flash(t('Task created successfully.'));
|
}
|
||||||
|
else {
|
||||||
if (isset($values['another_task']) && $values['another_task'] == 1) {
|
$this->session->flashError(t('Unable to create your task.'));
|
||||||
unset($values['title']);
|
|
||||||
unset($values['description']);
|
|
||||||
$this->response->redirect($this->helper->url->to('taskcreation', 'create', $values));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $project['id'])));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$this->session->flashError(t('Unable to create your task.'));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->create($values, $errors);
|
$this->create($values, $errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function afterSave(array $project, array &$values)
|
||||||
|
{
|
||||||
|
if (isset($values['another_task']) && $values['another_task'] == 1) {
|
||||||
|
unset($values['title']);
|
||||||
|
unset($values['description']);
|
||||||
|
|
||||||
|
if (! $this->request->isAjax()) {
|
||||||
|
$this->response->redirect($this->helper->url->to('taskcreation', 'create', $values));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $project['id'])));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ class Taskduplication extends Base
|
||||||
|
|
||||||
if ($task_id > 0) {
|
if ($task_id > 0) {
|
||||||
$this->session->flash(t('Task created successfully.'));
|
$this->session->flash(t('Task created successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])));
|
$this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task_id)));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to create this task.'));
|
$this->session->flashError(t('Unable to create this task.'));
|
||||||
$this->response->redirect($this->helper->url->to('taskduplication', 'duplicate', array('project_id' => $task['project_id'], 'task_id' => $task['id'])));
|
$this->response->redirect($this->helper->url->to('taskduplication', 'duplicate', array('project_id' => $task['project_id'], 'task_id' => $task['id'])));
|
||||||
|
@ -83,15 +83,16 @@ class Taskduplication extends Base
|
||||||
$values = $this->request->getValues();
|
$values = $this->request->getValues();
|
||||||
list($valid,) = $this->taskValidator->validateProjectModification($values);
|
list($valid,) = $this->taskValidator->validateProjectModification($values);
|
||||||
|
|
||||||
if ($valid && $this->taskDuplication->duplicateToProject($task['id'],
|
if ($valid) {
|
||||||
$values['project_id'],
|
$task_id = $this->taskDuplication->duplicateToProject(
|
||||||
$values['swimlane_id'],
|
$task['id'], $values['project_id'], $values['swimlane_id'],
|
||||||
$values['column_id'],
|
$values['column_id'], $values['category_id'], $values['owner_id']
|
||||||
$values['category_id'],
|
);
|
||||||
$values['owner_id'])) {
|
|
||||||
|
|
||||||
$this->session->flash(t('Task created successfully.'));
|
if ($task_id > 0) {
|
||||||
$this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])));
|
$this->session->flash(t('Task created successfully.'));
|
||||||
|
$this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $values['project_id'], 'task_id' => $task_id)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->session->flashError(t('Unable to create your task.'));
|
$this->session->flashError(t('Unable to create your task.'));
|
||||||
|
|
|
@ -126,11 +126,13 @@ class Taskmodification extends Base
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($ajax) {
|
if ($ajax) {
|
||||||
$this->response->html($this->template->render('task_modification/edit_task', $params));
|
$html = $this->template->render('task_modification/edit_task', $params);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$this->response->html($this->taskLayout('task_modification/edit_task', $params));
|
$html = $this->taskLayout('task_modification/edit_task', $params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->response->html($html);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -145,24 +147,20 @@ class Taskmodification extends Base
|
||||||
|
|
||||||
list($valid, $errors) = $this->taskValidator->validateModification($values);
|
list($valid, $errors) = $this->taskValidator->validateModification($values);
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid && $this->taskModification->update($values)) {
|
||||||
|
$this->session->flash(t('Task updated successfully.'));
|
||||||
|
|
||||||
if ($this->taskModification->update($values)) {
|
if ($this->request->isAjax()) {
|
||||||
$this->session->flash(t('Task updated successfully.'));
|
$this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $task['project_id'])));
|
||||||
|
|
||||||
if ($this->request->getIntegerParam('ajax')) {
|
|
||||||
$this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $task['project_id'])));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$this->session->flashError(t('Unable to update your task.'));
|
$this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
$this->edit($values, $errors);
|
$this->session->flashError(t('Unable to update your task.'));
|
||||||
|
$this->edit($values, $errors);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -18,36 +18,8 @@ class Taskstatus extends Base
|
||||||
public function close()
|
public function close()
|
||||||
{
|
{
|
||||||
$task = $this->getTask();
|
$task = $this->getTask();
|
||||||
$redirect = $this->request->getStringParam('redirect');
|
$this->changeStatus($task, 'close', t('Task closed successfully.'), t('Unable to close this task.'));
|
||||||
|
$this->renderTemplate($task, 'task_status/close');
|
||||||
if ($this->request->getStringParam('confirmation') === 'yes') {
|
|
||||||
|
|
||||||
$this->checkCSRFParam();
|
|
||||||
|
|
||||||
if ($this->taskStatus->close($task['id'])) {
|
|
||||||
$this->session->flash(t('Task closed successfully.'));
|
|
||||||
} else {
|
|
||||||
$this->session->flashError(t('Unable to close this task.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($redirect === 'board') {
|
|
||||||
$this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $task['project_id'])));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->request->isAjax()) {
|
|
||||||
$this->response->html($this->template->render('task_status/close', array(
|
|
||||||
'task' => $task,
|
|
||||||
'redirect' => $redirect,
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->response->html($this->taskLayout('task_status/close', array(
|
|
||||||
'task' => $task,
|
|
||||||
'redirect' => $redirect,
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -58,22 +30,44 @@ class Taskstatus extends Base
|
||||||
public function open()
|
public function open()
|
||||||
{
|
{
|
||||||
$task = $this->getTask();
|
$task = $this->getTask();
|
||||||
|
$this->changeStatus($task, 'open', t('Task opened successfully.'), t('Unable to open this task.'));
|
||||||
|
$this->renderTemplate($task, 'task_status/open');
|
||||||
|
}
|
||||||
|
|
||||||
|
private function changeStatus(array $task, $method, $success_message, $failure_message)
|
||||||
|
{
|
||||||
if ($this->request->getStringParam('confirmation') === 'yes') {
|
if ($this->request->getStringParam('confirmation') === 'yes') {
|
||||||
|
|
||||||
$this->checkCSRFParam();
|
$this->checkCSRFParam();
|
||||||
|
|
||||||
if ($this->taskStatus->open($task['id'])) {
|
if ($this->taskStatus->$method($task['id'])) {
|
||||||
$this->session->flash(t('Task opened successfully.'));
|
$this->session->flash($success_message);
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to open this task.'));
|
$this->session->flashError($failure_message);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])));
|
if ($this->request->getStringParam('redirect') === 'board') {
|
||||||
|
$this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $task['project_id'])));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function renderTemplate(array $task, $template)
|
||||||
|
{
|
||||||
|
$redirect = $this->request->getStringParam('redirect');
|
||||||
|
|
||||||
|
if ($this->request->isAjax()) {
|
||||||
|
$this->response->html($this->template->render($template, array(
|
||||||
|
'task' => $task,
|
||||||
|
'redirect' => $redirect,
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->html($this->taskLayout('task_status/open', array(
|
$this->response->html($this->taskLayout($template, array(
|
||||||
'task' => $task,
|
'task' => $task,
|
||||||
|
'redirect' => $redirect,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Controller;
|
|
||||||
|
|
||||||
use DateTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Timetable controller
|
|
||||||
*
|
|
||||||
* @package controller
|
|
||||||
* @author Frederic Guillot
|
|
||||||
*/
|
|
||||||
class Timetable extends User
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Display timetable for the user
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function index()
|
|
||||||
{
|
|
||||||
$user = $this->getUser();
|
|
||||||
$from = $this->request->getStringParam('from', date('Y-m-d'));
|
|
||||||
$to = $this->request->getStringParam('to', date('Y-m-d', strtotime('next week')));
|
|
||||||
$timetable = $this->timetable->calculate($user['id'], new DateTime($from), new DateTime($to));
|
|
||||||
|
|
||||||
$this->response->html($this->layout('timetable/index', array(
|
|
||||||
'user' => $user,
|
|
||||||
'timetable' => $timetable,
|
|
||||||
'values' => array(
|
|
||||||
'from' => $from,
|
|
||||||
'to' => $to,
|
|
||||||
'controller' => 'timetable',
|
|
||||||
'action' => 'index',
|
|
||||||
'user_id' => $user['id'],
|
|
||||||
),
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,88 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Controller;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Day Timetable controller
|
|
||||||
*
|
|
||||||
* @package controller
|
|
||||||
* @author Frederic Guillot
|
|
||||||
*/
|
|
||||||
class Timetableday extends User
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Display timetable for the user
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function index(array $values = array(), array $errors = array())
|
|
||||||
{
|
|
||||||
$user = $this->getUser();
|
|
||||||
|
|
||||||
$this->response->html($this->layout('timetable_day/index', array(
|
|
||||||
'timetable' => $this->timetableDay->getByUser($user['id']),
|
|
||||||
'values' => $values + array('user_id' => $user['id']),
|
|
||||||
'errors' => $errors,
|
|
||||||
'user' => $user,
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate and save
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function save()
|
|
||||||
{
|
|
||||||
$values = $this->request->getValues();
|
|
||||||
list($valid, $errors) = $this->timetableDay->validateCreation($values);
|
|
||||||
|
|
||||||
if ($valid) {
|
|
||||||
|
|
||||||
if ($this->timetableDay->create($values['user_id'], $values['start'], $values['end'])) {
|
|
||||||
$this->session->flash(t('Time slot created successfully.'));
|
|
||||||
$this->response->redirect($this->helper->url->to('timetableday', 'index', array('user_id' => $values['user_id'])));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$this->session->flashError(t('Unable to save this time slot.'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->index($values, $errors);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Confirmation dialag box to remove a row
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function confirm()
|
|
||||||
{
|
|
||||||
$user = $this->getUser();
|
|
||||||
|
|
||||||
$this->response->html($this->layout('timetable_day/remove', array(
|
|
||||||
'slot_id' => $this->request->getIntegerParam('slot_id'),
|
|
||||||
'user' => $user,
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a row
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function remove()
|
|
||||||
{
|
|
||||||
$this->checkCSRFParam();
|
|
||||||
$user = $this->getUser();
|
|
||||||
|
|
||||||
if ($this->timetableDay->remove($this->request->getIntegerParam('slot_id'))) {
|
|
||||||
$this->session->flash(t('Time slot removed successfully.'));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$this->session->flash(t('Unable to remove this time slot.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('timetableday', 'index', array('user_id' => $user['id'])));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Controller;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Over-time Timetable controller
|
|
||||||
*
|
|
||||||
* @package controller
|
|
||||||
* @author Frederic Guillot
|
|
||||||
*/
|
|
||||||
class Timetableextra extends Timetableoff
|
|
||||||
{
|
|
||||||
protected $model = 'timetableExtra';
|
|
||||||
protected $controller_url = 'timetableextra';
|
|
||||||
protected $template_dir = 'timetable_extra';
|
|
||||||
}
|
|
|
@ -1,107 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Controller;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Time-off Timetable controller
|
|
||||||
*
|
|
||||||
* @package controller
|
|
||||||
* @author Frederic Guillot
|
|
||||||
*/
|
|
||||||
class Timetableoff extends User
|
|
||||||
{
|
|
||||||
protected $model = 'timetableOff';
|
|
||||||
protected $controller_url = 'timetableoff';
|
|
||||||
protected $template_dir = 'timetable_off';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display timetable for the user
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function index(array $values = array(), array $errors = array())
|
|
||||||
{
|
|
||||||
$user = $this->getUser();
|
|
||||||
|
|
||||||
$paginator = $this->paginator
|
|
||||||
->setUrl($this->controller_url, 'index', array('user_id' => $user['id']))
|
|
||||||
->setMax(10)
|
|
||||||
->setOrder('date')
|
|
||||||
->setDirection('desc')
|
|
||||||
->setQuery($this->{$this->model}->getUserQuery($user['id']))
|
|
||||||
->calculate();
|
|
||||||
|
|
||||||
$this->response->html($this->layout($this->template_dir.'/index', array(
|
|
||||||
'values' => $values + array('user_id' => $user['id']),
|
|
||||||
'errors' => $errors,
|
|
||||||
'paginator' => $paginator,
|
|
||||||
'user' => $user,
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate and save
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function save()
|
|
||||||
{
|
|
||||||
$values = $this->request->getValues();
|
|
||||||
list($valid, $errors) = $this->{$this->model}->validateCreation($values);
|
|
||||||
|
|
||||||
if ($valid) {
|
|
||||||
|
|
||||||
if ($this->{$this->model}->create(
|
|
||||||
$values['user_id'],
|
|
||||||
$values['date'],
|
|
||||||
isset($values['all_day']) && $values['all_day'] == 1,
|
|
||||||
$values['start'],
|
|
||||||
$values['end'],
|
|
||||||
$values['comment'])) {
|
|
||||||
|
|
||||||
$this->session->flash(t('Time slot created successfully.'));
|
|
||||||
$this->response->redirect($this->helper->url->to($this->controller_url, 'index', array('user_id' => $values['user_id'])));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$this->session->flashError(t('Unable to save this time slot.'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->index($values, $errors);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Confirmation dialag box to remove a row
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function confirm()
|
|
||||||
{
|
|
||||||
$user = $this->getUser();
|
|
||||||
|
|
||||||
$this->response->html($this->layout($this->template_dir.'/remove', array(
|
|
||||||
'slot_id' => $this->request->getIntegerParam('slot_id'),
|
|
||||||
'user' => $user,
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a row
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function remove()
|
|
||||||
{
|
|
||||||
$this->checkCSRFParam();
|
|
||||||
$user = $this->getUser();
|
|
||||||
|
|
||||||
if ($this->{$this->model}->remove($this->request->getIntegerParam('slot_id'))) {
|
|
||||||
$this->session->flash(t('Time slot removed successfully.'));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$this->session->flash(t('Unable to remove this time slot.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to($this->controller_url, 'index', array('user_id' => $user['id'])));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,99 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Controller;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Week Timetable controller
|
|
||||||
*
|
|
||||||
* @package controller
|
|
||||||
* @author Frederic Guillot
|
|
||||||
*/
|
|
||||||
class Timetableweek extends User
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Display timetable for the user
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function index(array $values = array(), array $errors = array())
|
|
||||||
{
|
|
||||||
$user = $this->getUser();
|
|
||||||
|
|
||||||
if (empty($values)) {
|
|
||||||
|
|
||||||
$day = $this->timetableDay->getByUser($user['id']);
|
|
||||||
|
|
||||||
$values = array(
|
|
||||||
'user_id' => $user['id'],
|
|
||||||
'start' => isset($day[0]['start']) ? $day[0]['start'] : null,
|
|
||||||
'end' => isset($day[0]['end']) ? $day[0]['end'] : null,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->response->html($this->layout('timetable_week/index', array(
|
|
||||||
'timetable' => $this->timetableWeek->getByUser($user['id']),
|
|
||||||
'values' => $values,
|
|
||||||
'errors' => $errors,
|
|
||||||
'user' => $user,
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate and save
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function save()
|
|
||||||
{
|
|
||||||
$values = $this->request->getValues();
|
|
||||||
list($valid, $errors) = $this->timetableWeek->validateCreation($values);
|
|
||||||
|
|
||||||
if ($valid) {
|
|
||||||
|
|
||||||
if ($this->timetableWeek->create($values['user_id'], $values['day'], $values['start'], $values['end'])) {
|
|
||||||
$this->session->flash(t('Time slot created successfully.'));
|
|
||||||
$this->response->redirect($this->helper->url->to('timetableweek', 'index', array('user_id' => $values['user_id'])));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$this->session->flashError(t('Unable to save this time slot.'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->index($values, $errors);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Confirmation dialag box to remove a row
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function confirm()
|
|
||||||
{
|
|
||||||
$user = $this->getUser();
|
|
||||||
|
|
||||||
$this->response->html($this->layout('timetable_week/remove', array(
|
|
||||||
'slot_id' => $this->request->getIntegerParam('slot_id'),
|
|
||||||
'user' => $user,
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a row
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function remove()
|
|
||||||
{
|
|
||||||
$this->checkCSRFParam();
|
|
||||||
$user = $this->getUser();
|
|
||||||
|
|
||||||
if ($this->timetableWeek->remove($this->request->getIntegerParam('slot_id'))) {
|
|
||||||
$this->session->flash(t('Time slot removed successfully.'));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$this->session->flash(t('Unable to remove this time slot.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('timetableweek', 'index', array('user_id' => $user['id'])));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
namespace Controller;
|
namespace Controller;
|
||||||
|
|
||||||
|
use Model\NotificationType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User controller
|
* User controller
|
||||||
*
|
*
|
||||||
|
@ -92,6 +94,11 @@ class User extends Base
|
||||||
|
|
||||||
if ($user_id !== false) {
|
if ($user_id !== false) {
|
||||||
$this->projectPermission->addMember($project_id, $user_id);
|
$this->projectPermission->addMember($project_id, $user_id);
|
||||||
|
|
||||||
|
if (! empty($values['notifications_enabled'])) {
|
||||||
|
$this->notificationType->saveUserSelectedTypes($user_id, array(NotificationType::TYPE_EMAIL));
|
||||||
|
}
|
||||||
|
|
||||||
$this->session->flash(t('User created successfully.'));
|
$this->session->flash(t('User created successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('user', 'show', array('user_id' => $user_id)));
|
$this->response->redirect($this->helper->url->to('user', 'show', array('user_id' => $user_id)));
|
||||||
}
|
}
|
||||||
|
@ -202,6 +209,8 @@ class User extends Base
|
||||||
$this->response->html($this->layout('user/notifications', array(
|
$this->response->html($this->layout('user/notifications', array(
|
||||||
'projects' => $this->projectPermission->getMemberProjects($user['id']),
|
'projects' => $this->projectPermission->getMemberProjects($user['id']),
|
||||||
'notifications' => $this->notification->readSettings($user['id']),
|
'notifications' => $this->notification->readSettings($user['id']),
|
||||||
|
'types' => $this->notificationType->getTypes(),
|
||||||
|
'filters' => $this->notificationFilter->getFilters(),
|
||||||
'user' => $user,
|
'user' => $user,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
39
sources/app/Controller/Webnotification.php
Normal file
39
sources/app/Controller/Webnotification.php
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Controller;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Web notification controller
|
||||||
|
*
|
||||||
|
* @package controller
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class Webnotification extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Mark all notifications as read
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function flush()
|
||||||
|
{
|
||||||
|
$user_id = $this->userSession->getId();
|
||||||
|
|
||||||
|
$this->webNotification->markAllAsRead($user_id);
|
||||||
|
$this->response->redirect($this->helper->url->to('app', 'notifications', array('user_id' => $user_id)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark a notification as read
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function remove()
|
||||||
|
{
|
||||||
|
$user_id = $this->userSession->getId();
|
||||||
|
$notification_id = $this->request->getIntegerParam('notification_id');
|
||||||
|
|
||||||
|
$this->webNotification->markAsRead($user_id, $notification_id);
|
||||||
|
$this->response->redirect($this->helper->url->to('app', 'notifications', array('user_id' => $user_id)));
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,78 +10,86 @@ use Pimple\Container;
|
||||||
* @package core
|
* @package core
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*
|
*
|
||||||
* @property \Core\Helper $helper
|
* @property \Core\Helper $helper
|
||||||
* @property \Core\EmailClient $emailClient
|
* @property \Core\EmailClient $emailClient
|
||||||
* @property \Core\HttpClient $httpClient
|
* @property \Core\HttpClient $httpClient
|
||||||
* @property \Core\Paginator $paginator
|
* @property \Core\Paginator $paginator
|
||||||
* @property \Core\Request $request
|
* @property \Core\Request $request
|
||||||
* @property \Core\Session $session
|
* @property \Core\Session $session
|
||||||
* @property \Core\Template $template
|
* @property \Core\Template $template
|
||||||
* @property \Core\MemoryCache $memoryCache
|
* @property \Core\OAuth2 $oauth
|
||||||
* @property \Core\OAuth2 $oauth
|
* @property \Core\Router $router
|
||||||
* @property \Core\Router $router
|
* @property \Core\Lexer $lexer
|
||||||
* @property \Core\Lexer $lexer
|
* @property \Core\ObjectStorage\ObjectStorageInterface $objectStorage
|
||||||
* @property \Integration\BitbucketWebhook $bitbucketWebhook
|
* @property \Core\Cache\Cache $memoryCache
|
||||||
* @property \Integration\GithubWebhook $githubWebhook
|
* @property \Core\Plugin\Hook $hook
|
||||||
* @property \Integration\GitlabWebhook $gitlabWebhook
|
* @property \Core\Plugin\Loader $pluginLoader
|
||||||
* @property \Integration\HipchatWebhook $hipchatWebhook
|
* @property \Integration\BitbucketWebhook $bitbucketWebhook
|
||||||
* @property \Integration\Jabber $jabber
|
* @property \Integration\GithubWebhook $githubWebhook
|
||||||
* @property \Integration\Mailgun $mailgun
|
* @property \Integration\GitlabWebhook $gitlabWebhook
|
||||||
* @property \Integration\Postmark $postmark
|
* @property \Integration\HipchatWebhook $hipchatWebhook
|
||||||
* @property \Integration\Sendgrid $sendgrid
|
* @property \Integration\Jabber $jabber
|
||||||
* @property \Integration\SlackWebhook $slackWebhook
|
* @property \Integration\Mailgun $mailgun
|
||||||
* @property \Integration\Smtp $smtp
|
* @property \Integration\Postmark $postmark
|
||||||
* @property \Model\Acl $acl
|
* @property \Integration\Sendgrid $sendgrid
|
||||||
* @property \Model\Action $action
|
* @property \Integration\SlackWebhook $slackWebhook
|
||||||
* @property \Model\Authentication $authentication
|
* @property \Integration\Smtp $smtp
|
||||||
* @property \Model\Board $board
|
* @property \Formatter\ProjectGanttFormatter $projectGanttFormatter
|
||||||
* @property \Model\Budget $budget
|
* @property \Formatter\TaskFilterGanttFormatter $taskFilterGanttFormatter
|
||||||
* @property \Model\Category $category
|
* @property \Formatter\TaskFilterAutoCompleteFormatter $taskFilterAutoCompleteFormatter
|
||||||
* @property \Model\Color $color
|
* @property \Formatter\TaskFilterCalendarFormatter $taskFilterCalendarFormatter
|
||||||
* @property \Model\Comment $comment
|
* @property \Formatter\TaskFilterICalendarFormatter $taskFilterICalendarFormatter
|
||||||
* @property \Model\Config $config
|
* @property \Model\Acl $acl
|
||||||
* @property \Model\Currency $currency
|
* @property \Model\Action $action
|
||||||
* @property \Model\DateParser $dateParser
|
* @property \Model\Authentication $authentication
|
||||||
* @property \Model\File $file
|
* @property \Model\Board $board
|
||||||
* @property \Model\HourlyRate $hourlyRate
|
* @property \Model\Category $category
|
||||||
* @property \Model\LastLogin $lastLogin
|
* @property \Model\Color $color
|
||||||
* @property \Model\Link $link
|
* @property \Model\Comment $comment
|
||||||
* @property \Model\Notification $notification
|
* @property \Model\Config $config
|
||||||
* @property \Model\Project $project
|
* @property \Model\Currency $currency
|
||||||
* @property \Model\ProjectActivity $projectActivity
|
* @property \Model\CustomFilter $customFilter
|
||||||
* @property \Model\ProjectAnalytic $projectAnalytic
|
* @property \Model\DateParser $dateParser
|
||||||
* @property \Model\ProjectDuplication $projectDuplication
|
* @property \Model\File $file
|
||||||
* @property \Model\ProjectDailyColumnStats $projectDailyColumnStats
|
* @property \Model\LastLogin $lastLogin
|
||||||
* @property \Model\ProjectDailyStats $projectDailyStats
|
* @property \Model\Link $link
|
||||||
* @property \Model\ProjectIntegration $projectIntegration
|
* @property \Model\Notification $notification
|
||||||
* @property \Model\ProjectPermission $projectPermission
|
* @property \Model\NotificationType $notificationType
|
||||||
* @property \Model\Subtask $subtask
|
* @property \Model\NotificationFilter $notificationFilter
|
||||||
* @property \Model\SubtaskExport $subtaskExport
|
* @property \Model\OverdueNotification $overdueNotification
|
||||||
* @property \Model\SubtaskForecast $subtaskForecast
|
* @property \Model\WebNotification $webNotification
|
||||||
* @property \Model\SubtaskTimeTracking $subtaskTimeTracking
|
* @property \Model\Project $project
|
||||||
* @property \Model\Swimlane $swimlane
|
* @property \Model\ProjectActivity $projectActivity
|
||||||
* @property \Model\Task $task
|
* @property \Model\ProjectAnalytic $projectAnalytic
|
||||||
* @property \Model\TaskAnalytic $taskAnalytic
|
* @property \Model\ProjectDuplication $projectDuplication
|
||||||
* @property \Model\TaskCreation $taskCreation
|
* @property \Model\ProjectDailyColumnStats $projectDailyColumnStats
|
||||||
* @property \Model\TaskDuplication $taskDuplication
|
* @property \Model\ProjectDailyStats $projectDailyStats
|
||||||
* @property \Model\TaskExport $taskExport
|
* @property \Model\ProjectIntegration $projectIntegration
|
||||||
* @property \Model\TaskFinder $taskFinder
|
* @property \Model\ProjectPermission $projectPermission
|
||||||
* @property \Model\TaskFilter $taskFilter
|
* @property \Model\Subtask $subtask
|
||||||
* @property \Model\TaskLink $taskLink
|
* @property \Model\SubtaskExport $subtaskExport
|
||||||
* @property \Model\TaskModification $taskModification
|
* @property \Model\SubtaskTimeTracking $subtaskTimeTracking
|
||||||
* @property \Model\TaskPermission $taskPermission
|
* @property \Model\Swimlane $swimlane
|
||||||
* @property \Model\TaskPosition $taskPosition
|
* @property \Model\Task $task
|
||||||
* @property \Model\TaskStatus $taskStatus
|
* @property \Model\TaskAnalytic $taskAnalytic
|
||||||
* @property \Model\TaskValidator $taskValidator
|
* @property \Model\TaskCreation $taskCreation
|
||||||
* @property \Model\Timetable $timetable
|
* @property \Model\TaskDuplication $taskDuplication
|
||||||
* @property \Model\TimetableDay $timetableDay
|
* @property \Model\TaskExport $taskExport
|
||||||
* @property \Model\TimetableExtra $timetableExtra
|
* @property \Model\TaskFinder $taskFinder
|
||||||
* @property \Model\TimetableOff $timetableOff
|
* @property \Model\TaskFilter $taskFilter
|
||||||
* @property \Model\TimetableWeek $timetableWeek
|
* @property \Model\TaskLink $taskLink
|
||||||
* @property \Model\Transition $transition
|
* @property \Model\TaskModification $taskModification
|
||||||
* @property \Model\User $user
|
* @property \Model\TaskPermission $taskPermission
|
||||||
* @property \Model\UserSession $userSession
|
* @property \Model\TaskPosition $taskPosition
|
||||||
* @property \Model\Webhook $webhook
|
* @property \Model\TaskStatus $taskStatus
|
||||||
|
* @property \Model\TaskValidator $taskValidator
|
||||||
|
* @property \Model\Transition $transition
|
||||||
|
* @property \Model\User $user
|
||||||
|
* @property \Model\UserSession $userSession
|
||||||
|
* @property \Model\Webhook $webhook
|
||||||
|
* @property \Psr\Log\LoggerInterface $logger
|
||||||
|
* @property \League\HTMLToMarkdown\HtmlConverter $htmlConverter
|
||||||
|
* @property \PicoDb\Database $db
|
||||||
*/
|
*/
|
||||||
abstract class Base
|
abstract class Base
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Core;
|
|
||||||
|
|
||||||
use Pimple\Container;
|
|
||||||
|
|
||||||
abstract class Cache
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Container instance
|
|
||||||
*
|
|
||||||
* @access protected
|
|
||||||
* @var \Pimple\Container
|
|
||||||
*/
|
|
||||||
protected $container;
|
|
||||||
|
|
||||||
abstract public function init();
|
|
||||||
abstract public function set($key, $value);
|
|
||||||
abstract public function get($key);
|
|
||||||
abstract public function flush();
|
|
||||||
abstract public function remove($key);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param \Pimple\Container $container
|
|
||||||
*/
|
|
||||||
public function __construct(Container $container)
|
|
||||||
{
|
|
||||||
$this->container = $container;
|
|
||||||
$this->init();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Proxy cache
|
|
||||||
*
|
|
||||||
* Note: Arguments must be scalar types
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param string $container Container name
|
|
||||||
* @param string $method Container method
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function proxy($container, $method)
|
|
||||||
{
|
|
||||||
$args = func_get_args();
|
|
||||||
$key = 'proxy_'.implode('_', $args);
|
|
||||||
$result = $this->get($key);
|
|
||||||
|
|
||||||
if ($result === null) {
|
|
||||||
$result = call_user_func_array(array($this->container[$container], $method), array_splice($args, 2));
|
|
||||||
$this->set($key, $result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
}
|
|
38
sources/app/Core/Cache/Base.php
Normal file
38
sources/app/Core/Cache/Base.php
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Core\Cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for cache drivers
|
||||||
|
*
|
||||||
|
* @package cache
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
abstract class Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Proxy cache
|
||||||
|
*
|
||||||
|
* Note: Arguments must be scalar types
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $class Class instance
|
||||||
|
* @param string $method Container method
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function proxy($class, $method)
|
||||||
|
{
|
||||||
|
$args = func_get_args();
|
||||||
|
array_shift($args);
|
||||||
|
|
||||||
|
$key = 'proxy:'.get_class($class).':'.implode(':', $args);
|
||||||
|
$result = $this->get($key);
|
||||||
|
|
||||||
|
if ($result === null) {
|
||||||
|
$result = call_user_func_array(array($class, $method), array_splice($args, 1));
|
||||||
|
$this->set($key, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
45
sources/app/Core/Cache/CacheInterface.php
Normal file
45
sources/app/Core/Cache/CacheInterface.php
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Core\Cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache Interface
|
||||||
|
*
|
||||||
|
* @package cache
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
interface CacheInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Save a new value in the cache
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $key
|
||||||
|
* @param string $value
|
||||||
|
*/
|
||||||
|
public function set($key, $value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch value from cache
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $key
|
||||||
|
* @return mixed Null when not found, cached value otherwise
|
||||||
|
*/
|
||||||
|
public function get($key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear all cache
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function flush();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove cached value
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $key
|
||||||
|
*/
|
||||||
|
public function remove($key);
|
||||||
|
}
|
65
sources/app/Core/Cache/MemoryCache.php
Normal file
65
sources/app/Core/Cache/MemoryCache.php
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Core\Cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Memory Cache
|
||||||
|
*
|
||||||
|
* @package cache
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class MemoryCache extends Base implements CacheInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Container
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $storage = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save a new value in the cache
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $key
|
||||||
|
* @param string $value
|
||||||
|
*/
|
||||||
|
public function set($key, $value)
|
||||||
|
{
|
||||||
|
$this->storage[$key] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch value from cache
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $key
|
||||||
|
* @return mixed Null when not found, cached value otherwise
|
||||||
|
*/
|
||||||
|
public function get($key)
|
||||||
|
{
|
||||||
|
return isset($this->storage[$key]) ? $this->storage[$key] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear all cache
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function flush()
|
||||||
|
{
|
||||||
|
$this->storage = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove cached value
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $key
|
||||||
|
*/
|
||||||
|
public function remove($key)
|
||||||
|
{
|
||||||
|
unset($this->storage[$key]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -99,9 +99,18 @@ class HttpClient extends Base
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
$headers = array_merge(array('User-Agent: '.self::HTTP_USER_AGENT, 'Connection: close'), $headers);
|
$default_headers = array(
|
||||||
|
'User-Agent: '.self::HTTP_USER_AGENT,
|
||||||
|
'Connection: close',
|
||||||
|
);
|
||||||
|
|
||||||
$context = stream_context_create(array(
|
if (HTTP_PROXY_USERNAME) {
|
||||||
|
$default_headers[] = 'Proxy-Authorization: Basic '.base64_encode(HTTP_PROXY_USERNAME.':'.HTTP_PROXY_PASSWORD);
|
||||||
|
}
|
||||||
|
|
||||||
|
$headers = array_merge($default_headers, $headers);
|
||||||
|
|
||||||
|
$context = array(
|
||||||
'http' => array(
|
'http' => array(
|
||||||
'method' => $method,
|
'method' => $method,
|
||||||
'protocol_version' => 1.1,
|
'protocol_version' => 1.1,
|
||||||
|
@ -110,9 +119,14 @@ class HttpClient extends Base
|
||||||
'header' => implode("\r\n", $headers),
|
'header' => implode("\r\n", $headers),
|
||||||
'content' => $content
|
'content' => $content
|
||||||
)
|
)
|
||||||
));
|
);
|
||||||
|
|
||||||
$stream = @fopen(trim($url), 'r', false, $context);
|
if (HTTP_PROXY_HOSTNAME) {
|
||||||
|
$context['http']['proxy'] = 'tcp://'.HTTP_PROXY_HOSTNAME.':'.HTTP_PROXY_PORT;
|
||||||
|
$context['http']['request_fulluri'] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$stream = @fopen(trim($url), 'r', false, stream_context_create($context));
|
||||||
$response = '';
|
$response = '';
|
||||||
|
|
||||||
if (is_resource($stream)) {
|
if (is_resource($stream)) {
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Core;
|
|
||||||
|
|
||||||
class MemoryCache extends Cache
|
|
||||||
{
|
|
||||||
private $storage = array();
|
|
||||||
|
|
||||||
public function init()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public function set($key, $value)
|
|
||||||
{
|
|
||||||
$this->storage[$key] = $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function get($key)
|
|
||||||
{
|
|
||||||
return isset($this->storage[$key]) ? $this->storage[$key] : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function flush()
|
|
||||||
{
|
|
||||||
$this->storage = array();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function remove($key)
|
|
||||||
{
|
|
||||||
unset($this->storage[$key]);
|
|
||||||
}
|
|
||||||
}
|
|
22
sources/app/Core/NotificationInterface.php
Normal file
22
sources/app/Core/NotificationInterface.php
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notification Interface
|
||||||
|
*
|
||||||
|
* @package core
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
interface NotificationInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Send notification to someone
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $user
|
||||||
|
* @param string $event_name
|
||||||
|
* @param array $event_data
|
||||||
|
*/
|
||||||
|
public function send(array $user, $event_name, array $event_data);
|
||||||
|
}
|
149
sources/app/Core/ObjectStorage/FileStorage.php
Normal file
149
sources/app/Core/ObjectStorage/FileStorage.php
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Core\ObjectStorage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Local File Storage
|
||||||
|
*
|
||||||
|
* @package ObjectStorage
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class FileStorage implements ObjectStorageInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Base path
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $path = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $path
|
||||||
|
*/
|
||||||
|
public function __construct($path)
|
||||||
|
{
|
||||||
|
$this->path = $path;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch object contents
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $key
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function get($key)
|
||||||
|
{
|
||||||
|
$filename = $this->path.DIRECTORY_SEPARATOR.$key;
|
||||||
|
|
||||||
|
if (! file_exists($filename)) {
|
||||||
|
throw new ObjectStorageException('File not found: '.$filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
return file_get_contents($filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save object
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $key
|
||||||
|
* @param string $blob
|
||||||
|
*/
|
||||||
|
public function put($key, &$blob)
|
||||||
|
{
|
||||||
|
$this->createFolder($key);
|
||||||
|
|
||||||
|
if (file_put_contents($this->path.DIRECTORY_SEPARATOR.$key, $blob) === false) {
|
||||||
|
throw new ObjectStorageException('Unable to write the file: '.$this->path.DIRECTORY_SEPARATOR.$key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Output directly object content
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $key
|
||||||
|
*/
|
||||||
|
public function output($key)
|
||||||
|
{
|
||||||
|
$filename = $this->path.DIRECTORY_SEPARATOR.$key;
|
||||||
|
|
||||||
|
if (! file_exists($filename)) {
|
||||||
|
throw new ObjectStorageException('File not found: '.$filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
readfile($filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move local file to object storage
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $src_filename
|
||||||
|
* @param string $key
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function moveFile($src_filename, $key)
|
||||||
|
{
|
||||||
|
$this->createFolder($key);
|
||||||
|
$dst_filename = $this->path.DIRECTORY_SEPARATOR.$key;
|
||||||
|
|
||||||
|
if (! rename($src_filename, $dst_filename)) {
|
||||||
|
throw new ObjectStorageException('Unable to move the file: '.$src_filename.' to '.$dst_filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move uploaded file to object storage
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $filename
|
||||||
|
* @param string $key
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function moveUploadedFile($filename, $key)
|
||||||
|
{
|
||||||
|
$this->createFolder($key);
|
||||||
|
return move_uploaded_file($filename, $this->path.DIRECTORY_SEPARATOR.$key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove object
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $key
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function remove($key)
|
||||||
|
{
|
||||||
|
$filename = $this->path.DIRECTORY_SEPARATOR.$key;
|
||||||
|
|
||||||
|
if (file_exists($filename)) {
|
||||||
|
return unlink($filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create object folder
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param string $key
|
||||||
|
*/
|
||||||
|
private function createFolder($key)
|
||||||
|
{
|
||||||
|
$folder = strpos($key, '/') !== false ? $this->path.DIRECTORY_SEPARATOR.dirname($key) : $this->path;
|
||||||
|
|
||||||
|
if (! is_dir($folder) && ! mkdir($folder, 0755, true)) {
|
||||||
|
throw new ObjectStorageException('Unable to create folder: '.$folder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Core\ObjectStorage;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
class ObjectStorageException extends Exception
|
||||||
|
{
|
||||||
|
}
|
67
sources/app/Core/ObjectStorage/ObjectStorageInterface.php
Normal file
67
sources/app/Core/ObjectStorage/ObjectStorageInterface.php
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Core\ObjectStorage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Object Storage Interface
|
||||||
|
*
|
||||||
|
* @package ObjectStorage
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
interface ObjectStorageInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Fetch object contents
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $key
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function get($key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save object
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $key
|
||||||
|
* @param string $blob
|
||||||
|
*/
|
||||||
|
public function put($key, &$blob);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Output directly object content
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $key
|
||||||
|
*/
|
||||||
|
public function output($key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move local file to object storage
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $filename
|
||||||
|
* @param string $key
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function moveFile($filename, $key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move uploaded file to object storage
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $filename
|
||||||
|
* @param string $key
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function moveUploadedFile($filename, $key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove object
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $key
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function remove($key);
|
||||||
|
}
|
123
sources/app/Core/Plugin/Base.php
Normal file
123
sources/app/Core/Plugin/Base.php
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Core\Plugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin Base class
|
||||||
|
*
|
||||||
|
* @package plugin
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
abstract class Base extends \Core\Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Method called for each request
|
||||||
|
*
|
||||||
|
* @abstract
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
abstract public function initialize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override default CSP rules
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $rules
|
||||||
|
*/
|
||||||
|
public function setContentSecurityPolicy(array $rules)
|
||||||
|
{
|
||||||
|
$this->container['cspRules'] = $rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all classes that needs to be stored in the DI container
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getClasses()
|
||||||
|
{
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listen on internal events
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $event
|
||||||
|
* @param callable $callback
|
||||||
|
*/
|
||||||
|
public function on($event, $callback)
|
||||||
|
{
|
||||||
|
$container = $this->container;
|
||||||
|
|
||||||
|
$this->container['dispatcher']->addListener($event, function() use ($container, $callback) {
|
||||||
|
call_user_func($callback, $container);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get plugin name
|
||||||
|
*
|
||||||
|
* This method should be overrided by your Plugin class
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getPluginName()
|
||||||
|
{
|
||||||
|
return ucfirst(substr(get_called_class(), 7, -7));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get plugin description
|
||||||
|
*
|
||||||
|
* This method should be overrided by your Plugin class
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getPluginDescription()
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get plugin author
|
||||||
|
*
|
||||||
|
* This method should be overrided by your Plugin class
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getPluginAuthor()
|
||||||
|
{
|
||||||
|
return '?';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get plugin version
|
||||||
|
*
|
||||||
|
* This method should be overrided by your Plugin class
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getPluginVersion()
|
||||||
|
{
|
||||||
|
return '?';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get plugin homepage
|
||||||
|
*
|
||||||
|
* This method should be overrided by your Plugin class
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getPluginHomepage()
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
99
sources/app/Core/Plugin/Hook.php
Normal file
99
sources/app/Core/Plugin/Hook.php
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Core\Plugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin Hooks Handler
|
||||||
|
*
|
||||||
|
* @package plugin
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class Hook
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* List of hooks
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $hooks = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bind something on a hook
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $hook
|
||||||
|
* @param mixed $value
|
||||||
|
*/
|
||||||
|
public function on($hook, $value)
|
||||||
|
{
|
||||||
|
if (! isset($this->hooks[$hook])) {
|
||||||
|
$this->hooks[$hook] = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->hooks[$hook][] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all bindings for a hook
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $hook
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getListeners($hook)
|
||||||
|
{
|
||||||
|
return isset($this->hooks[$hook]) ? $this->hooks[$hook] : array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the hook is used
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $hook
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function exists($hook)
|
||||||
|
{
|
||||||
|
return isset($this->hooks[$hook]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge listener results with input array
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $hook
|
||||||
|
* @param array $values
|
||||||
|
* @param array $params
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function merge($hook, array &$values, array $params = array())
|
||||||
|
{
|
||||||
|
foreach ($this->getListeners($hook) as $listener) {
|
||||||
|
$result = call_user_func_array($listener, $params);
|
||||||
|
|
||||||
|
if (is_array($result) && ! empty($result)) {
|
||||||
|
$values = array_merge($values, $result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $values;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute only first listener
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $hook
|
||||||
|
* @param array $params
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function first($hook, array $params = array())
|
||||||
|
{
|
||||||
|
foreach ($this->getListeners($hook) as $listener) {
|
||||||
|
return call_user_func_array($listener, $params);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
148
sources/app/Core/Plugin/Loader.php
Normal file
148
sources/app/Core/Plugin/Loader.php
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Core\Plugin;
|
||||||
|
|
||||||
|
use DirectoryIterator;
|
||||||
|
use PDOException;
|
||||||
|
use Core\Tool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin Loader
|
||||||
|
*
|
||||||
|
* @package plugin
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class Loader extends \Core\Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Schema version table for plugins
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const TABLE_SCHEMA = 'plugin_schema_versions';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin instances
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public $plugins = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scan plugin folder and load plugins
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function scan()
|
||||||
|
{
|
||||||
|
if (file_exists(PLUGINS_DIR)) {
|
||||||
|
$dir = new DirectoryIterator(PLUGINS_DIR);
|
||||||
|
|
||||||
|
foreach ($dir as $fileinfo) {
|
||||||
|
if (! $fileinfo->isDot() && $fileinfo->isDir()) {
|
||||||
|
$plugin = $fileinfo->getFilename();
|
||||||
|
$this->loadSchema($plugin);
|
||||||
|
$this->load($plugin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load plugin
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $plugin
|
||||||
|
*/
|
||||||
|
public function load($plugin)
|
||||||
|
{
|
||||||
|
$class = '\Plugin\\'.$plugin.'\\Plugin';
|
||||||
|
$instance = new $class($this->container);
|
||||||
|
|
||||||
|
Tool::buildDic($this->container, $instance->getClasses());
|
||||||
|
|
||||||
|
$instance->initialize();
|
||||||
|
$this->plugins[] = $instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load plugin schema
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $plugin
|
||||||
|
*/
|
||||||
|
public function loadSchema($plugin)
|
||||||
|
{
|
||||||
|
$filename = PLUGINS_DIR.'/'.$plugin.'/Schema/'.ucfirst(DB_DRIVER).'.php';
|
||||||
|
|
||||||
|
if (file_exists($filename)) {
|
||||||
|
require_once($filename);
|
||||||
|
$this->migrateSchema($plugin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute plugin schema migrations
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $plugin
|
||||||
|
*/
|
||||||
|
public function migrateSchema($plugin)
|
||||||
|
{
|
||||||
|
$last_version = constant('\Plugin\\'.$plugin.'\Schema\VERSION');
|
||||||
|
$current_version = $this->getSchemaVersion($plugin);
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
$this->db->startTransaction();
|
||||||
|
$this->db->getDriver()->disableForeignKeys();
|
||||||
|
|
||||||
|
for ($i = $current_version + 1; $i <= $last_version; $i++) {
|
||||||
|
$function_name = '\Plugin\\'.$plugin.'\Schema\version_'.$i;
|
||||||
|
|
||||||
|
if (function_exists($function_name)) {
|
||||||
|
call_user_func($function_name, $this->db->getConnection());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->db->getDriver()->enableForeignKeys();
|
||||||
|
$this->db->closeTransaction();
|
||||||
|
$this->setSchemaVersion($plugin, $i - 1);
|
||||||
|
}
|
||||||
|
catch (PDOException $e) {
|
||||||
|
$this->db->cancelTransaction();
|
||||||
|
$this->db->getDriver()->enableForeignKeys();
|
||||||
|
die('Unable to migrate schema for the plugin: '.$plugin.' => '.$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get current plugin schema version
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $plugin
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public function getSchemaVersion($plugin)
|
||||||
|
{
|
||||||
|
return (int) $this->db->table(self::TABLE_SCHEMA)->eq('plugin', strtolower($plugin))->findOneColumn('version');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save last plugin schema version
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $plugin
|
||||||
|
* @param integer $version
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function setSchemaVersion($plugin, $version)
|
||||||
|
{
|
||||||
|
$dictionary = array(
|
||||||
|
strtolower($plugin) => $version
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this->db->getDriver()->upsert(self::TABLE_SCHEMA, 'plugin', 'version', $dictionary);
|
||||||
|
}
|
||||||
|
}
|
|
@ -66,7 +66,13 @@ class Response
|
||||||
*/
|
*/
|
||||||
public function redirect($url)
|
public function redirect($url)
|
||||||
{
|
{
|
||||||
header('Location: '.$url);
|
if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest') {
|
||||||
|
header('X-Ajax-Redirect: '.$url);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
header('Location: '.$url);
|
||||||
|
}
|
||||||
|
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,7 +80,7 @@ class Router extends Base
|
||||||
$path = substr($path, 0, - strlen($query_string) - 1);
|
$path = substr($path, 0, - strlen($query_string) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($path{0} === '/') {
|
if (! empty($path) && $path{0} === '/') {
|
||||||
$path = substr($path, 1);
|
$path = substr($path, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,56 +206,22 @@ class Router extends Base
|
||||||
* @access public
|
* @access public
|
||||||
* @param string $uri
|
* @param string $uri
|
||||||
* @param string $query_string
|
* @param string $query_string
|
||||||
* @return boolean
|
|
||||||
*/
|
*/
|
||||||
public function dispatch($uri, $query_string = '')
|
public function dispatch($uri, $query_string = '')
|
||||||
{
|
{
|
||||||
if (! empty($_GET['controller']) && ! empty($_GET['action'])) {
|
if (! empty($_GET['controller']) && ! empty($_GET['action'])) {
|
||||||
$controller = $this->sanitize($_GET['controller'], 'app');
|
$this->controller = $this->sanitize($_GET['controller'], 'app');
|
||||||
$action = $this->sanitize($_GET['action'], 'index');
|
$this->action = $this->sanitize($_GET['action'], 'index');
|
||||||
|
$plugin = ! empty($_GET['plugin']) ? $this->sanitize($_GET['plugin'], '') : '';
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
list($controller, $action) = $this->findRoute($this->getPath($uri, $query_string));
|
list($this->controller, $this->action) = $this->findRoute($this->getPath($uri, $query_string)); // TODO: add plugin for routes
|
||||||
|
$plugin = '';
|
||||||
}
|
}
|
||||||
|
$class = empty($plugin) ? '\Controller\\'.ucfirst($this->controller) : '\Plugin\\'.ucfirst($plugin).'\Controller\\'.ucfirst($this->controller);
|
||||||
|
|
||||||
return $this->load(
|
$instance = new $class($this->container);
|
||||||
__DIR__.'/../Controller/'.ucfirst($controller).'.php',
|
$instance->beforeAction($this->controller, $this->action);
|
||||||
$controller,
|
$instance->{$this->action}();
|
||||||
'\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
|
|
||||||
*/
|
|
||||||
private function load($filename, $controller, $class, $method)
|
|
||||||
{
|
|
||||||
if (file_exists($filename)) {
|
|
||||||
|
|
||||||
require $filename;
|
|
||||||
|
|
||||||
if (! method_exists($class, $method)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->action = $method;
|
|
||||||
$this->controller = $controller;
|
|
||||||
|
|
||||||
$instance = new $class($this->container);
|
|
||||||
$instance->beforeAction($controller, $method);
|
|
||||||
$instance->$method();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,9 @@ class Session implements ArrayAccess
|
||||||
ini_set('session.use_only_cookies', '1');
|
ini_set('session.use_only_cookies', '1');
|
||||||
|
|
||||||
// Enable strict mode
|
// Enable strict mode
|
||||||
ini_set('session.use_strict_mode', '1');
|
if (version_compare(PHP_VERSION, '7.0.0') < 0) {
|
||||||
|
ini_set('session.use_strict_mode', '1');
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure session ID integrity
|
// Ensure session ID integrity
|
||||||
ini_set('session.entropy_file', '/dev/urandom');
|
ini_set('session.entropy_file', '/dev/urandom');
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
namespace Core;
|
namespace Core;
|
||||||
|
|
||||||
use LogicException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Template class
|
* Template class
|
||||||
*
|
*
|
||||||
|
@ -13,11 +11,12 @@ use LogicException;
|
||||||
class Template extends Helper
|
class Template extends Helper
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Template path
|
* List of template overrides
|
||||||
*
|
*
|
||||||
* @var string
|
* @access private
|
||||||
|
* @var array
|
||||||
*/
|
*/
|
||||||
const PATH = 'app/Template/';
|
private $overrides = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render a template
|
* Render a template
|
||||||
|
@ -33,16 +32,10 @@ class Template extends Helper
|
||||||
*/
|
*/
|
||||||
public function render($__template_name, array $__template_args = array())
|
public function render($__template_name, array $__template_args = array())
|
||||||
{
|
{
|
||||||
$__template_file = self::PATH.$__template_name.'.php';
|
|
||||||
|
|
||||||
if (! file_exists($__template_file)) {
|
|
||||||
throw new LogicException('Unable to load the template: "'.$__template_name.'"');
|
|
||||||
}
|
|
||||||
|
|
||||||
extract($__template_args);
|
extract($__template_args);
|
||||||
|
|
||||||
ob_start();
|
ob_start();
|
||||||
include $__template_file;
|
include $this->getTemplateFile($__template_name);
|
||||||
return ob_get_clean();
|
return ob_get_clean();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,4 +55,41 @@ class Template extends Helper
|
||||||
$template_args + array('content_for_layout' => $this->render($template_name, $template_args))
|
$template_args + array('content_for_layout' => $this->render($template_name, $template_args))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define a new template override
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $original_template
|
||||||
|
* @param string $new_template
|
||||||
|
*/
|
||||||
|
public function setTemplateOverride($original_template, $new_template)
|
||||||
|
{
|
||||||
|
$this->overrides[$original_template] = $new_template;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find template filename
|
||||||
|
*
|
||||||
|
* Core template name: 'task/show'
|
||||||
|
* Plugin template name: 'myplugin:task/show'
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $template_name
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getTemplateFile($template_name)
|
||||||
|
{
|
||||||
|
$template_name = isset($this->overrides[$template_name]) ? $this->overrides[$template_name] : $template_name;
|
||||||
|
|
||||||
|
if (strpos($template_name, ':') !== false) {
|
||||||
|
list($plugin, $template) = explode(':', $template_name);
|
||||||
|
$path = __DIR__.'/../../plugins/'.ucfirst($plugin).'/Template/'.$template.'.php';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$path = __DIR__.'/../Template/'.$template_name.'.php';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $path;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
namespace Core;
|
namespace Core;
|
||||||
|
|
||||||
|
use Pimple\Container;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tool class
|
* Tool class
|
||||||
*
|
*
|
||||||
|
@ -23,7 +25,6 @@ class Tool
|
||||||
$fp = fopen($filename, 'w');
|
$fp = fopen($filename, 'w');
|
||||||
|
|
||||||
if (is_resource($fp)) {
|
if (is_resource($fp)) {
|
||||||
|
|
||||||
foreach ($rows as $fields) {
|
foreach ($rows as $fields) {
|
||||||
fputcsv($fp, $fields);
|
fputcsv($fp, $fields);
|
||||||
}
|
}
|
||||||
|
@ -51,4 +52,102 @@ class Tool
|
||||||
|
|
||||||
return $identifier;
|
return $identifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build dependency injection container from an array
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @access public
|
||||||
|
* @param Container $container
|
||||||
|
* @param array $namespaces
|
||||||
|
*/
|
||||||
|
public static function buildDIC(Container $container, array $namespaces)
|
||||||
|
{
|
||||||
|
foreach ($namespaces as $namespace => $classes) {
|
||||||
|
foreach ($classes as $name) {
|
||||||
|
$class = '\\'.$namespace.'\\'.$name;
|
||||||
|
$container[lcfirst($name)] = function ($c) use ($class) {
|
||||||
|
return new $class($c);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a jpeg thumbnail from an image
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @access public
|
||||||
|
* @param string $src_file Source file image
|
||||||
|
* @param string $dst_file Destination file image
|
||||||
|
* @param integer $resize_width Desired image width
|
||||||
|
* @param integer $resize_height Desired image height
|
||||||
|
*/
|
||||||
|
public static function generateThumbnail($src_file, $dst_file, $resize_width = 250, $resize_height = 100)
|
||||||
|
{
|
||||||
|
$metadata = getimagesize($src_file);
|
||||||
|
$src_width = $metadata[0];
|
||||||
|
$src_height = $metadata[1];
|
||||||
|
$dst_y = 0;
|
||||||
|
$dst_x = 0;
|
||||||
|
|
||||||
|
if (empty($metadata['mime'])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($resize_width == 0 && $resize_height == 0) {
|
||||||
|
$resize_width = 100;
|
||||||
|
$resize_height = 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($resize_width > 0 && $resize_height == 0) {
|
||||||
|
$dst_width = $resize_width;
|
||||||
|
$dst_height = floor($src_height * ($resize_width / $src_width));
|
||||||
|
$dst_image = imagecreatetruecolor($dst_width, $dst_height);
|
||||||
|
}
|
||||||
|
elseif ($resize_width == 0 && $resize_height > 0) {
|
||||||
|
$dst_width = floor($src_width * ($resize_height / $src_height));
|
||||||
|
$dst_height = $resize_height;
|
||||||
|
$dst_image = imagecreatetruecolor($dst_width, $dst_height);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
$src_ratio = $src_width / $src_height;
|
||||||
|
$resize_ratio = $resize_width / $resize_height;
|
||||||
|
|
||||||
|
if ($src_ratio <= $resize_ratio) {
|
||||||
|
$dst_width = $resize_width;
|
||||||
|
$dst_height = floor($src_height * ($resize_width / $src_width));
|
||||||
|
|
||||||
|
$dst_y = ($dst_height - $resize_height) / 2 * (-1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$dst_width = floor($src_width * ($resize_height / $src_height));
|
||||||
|
$dst_height = $resize_height;
|
||||||
|
|
||||||
|
$dst_x = ($dst_width - $resize_width) / 2 * (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$dst_image = imagecreatetruecolor($resize_width, $resize_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($metadata['mime']) {
|
||||||
|
case 'image/jpeg':
|
||||||
|
case 'image/jpg':
|
||||||
|
$src_image = imagecreatefromjpeg($src_file);
|
||||||
|
break;
|
||||||
|
case 'image/png':
|
||||||
|
$src_image = imagecreatefrompng($src_file);
|
||||||
|
break;
|
||||||
|
case 'image/gif':
|
||||||
|
$src_image = imagecreatefromgif($src_file);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
imagecopyresampled($dst_image, $src_image, $dst_x, $dst_y, 0, 0, $dst_width, $dst_height, $src_width, $src_height);
|
||||||
|
imagejpeg($dst_image, $dst_file);
|
||||||
|
imagedestroy($dst_image);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ class Translator
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
const PATH = 'app/Locale/';
|
const PATH = 'app/Locale';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Locale
|
* Locale
|
||||||
|
@ -196,18 +196,27 @@ class Translator
|
||||||
* @static
|
* @static
|
||||||
* @access public
|
* @access public
|
||||||
* @param string $language Locale code: fr_FR
|
* @param string $language Locale code: fr_FR
|
||||||
|
* @param string $path Locale folder
|
||||||
*/
|
*/
|
||||||
public static function load($language)
|
public static function load($language, $path = self::PATH)
|
||||||
{
|
{
|
||||||
setlocale(LC_TIME, $language.'.UTF-8', $language);
|
setlocale(LC_TIME, $language.'.UTF-8', $language);
|
||||||
|
|
||||||
$filename = self::PATH.$language.DIRECTORY_SEPARATOR.'translations.php';
|
$filename = $path.DIRECTORY_SEPARATOR.$language.DIRECTORY_SEPARATOR.'translations.php';
|
||||||
|
|
||||||
if (file_exists($filename)) {
|
if (file_exists($filename)) {
|
||||||
self::$locales = require $filename;
|
self::$locales = array_merge(self::$locales, require($filename));
|
||||||
}
|
|
||||||
else {
|
|
||||||
self::$locales = array();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear locales stored in memory
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public static function unload()
|
||||||
|
{
|
||||||
|
self::$locales = array();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
14
sources/app/Formatter/FormatterInterface.php
Normal file
14
sources/app/Formatter/FormatterInterface.php
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Formatter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formatter Interface
|
||||||
|
*
|
||||||
|
* @package formatter
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
interface FormatterInterface
|
||||||
|
{
|
||||||
|
public function format();
|
||||||
|
}
|
90
sources/app/Formatter/ProjectGanttFormatter.php
Normal file
90
sources/app/Formatter/ProjectGanttFormatter.php
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Formatter;
|
||||||
|
|
||||||
|
use Model\Project;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gantt chart formatter for projects
|
||||||
|
*
|
||||||
|
* @package formatter
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class ProjectGanttFormatter extends Project implements FormatterInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* List of projects
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $projects = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter projects to generate the Gantt chart
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param int[] $project_ids
|
||||||
|
* @return ProjectGanttFormatter
|
||||||
|
*/
|
||||||
|
public function filter(array $project_ids)
|
||||||
|
{
|
||||||
|
if (empty($project_ids)) {
|
||||||
|
$this->projects = array();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
$this->projects = $this->db
|
||||||
|
->table(self::TABLE)
|
||||||
|
->asc('start_date')
|
||||||
|
->in('id', $project_ids)
|
||||||
|
->eq('is_active', self::ACTIVE)
|
||||||
|
->eq('is_private', 0)
|
||||||
|
->findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format projects to be displayed in the Gantt chart
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function format()
|
||||||
|
{
|
||||||
|
$colors = $this->color->getDefaultColors();
|
||||||
|
$bars = array();
|
||||||
|
|
||||||
|
foreach ($this->projects as $project) {
|
||||||
|
$start = empty($project['start_date']) ? time() : strtotime($project['start_date']);
|
||||||
|
$end = empty($project['end_date']) ? $start : strtotime($project['end_date']);
|
||||||
|
$color = next($colors) ?: reset($colors);
|
||||||
|
|
||||||
|
$bars[] = array(
|
||||||
|
'type' => 'project',
|
||||||
|
'id' => $project['id'],
|
||||||
|
'title' => $project['name'],
|
||||||
|
'start' => array(
|
||||||
|
(int) date('Y', $start),
|
||||||
|
(int) date('n', $start),
|
||||||
|
(int) date('j', $start),
|
||||||
|
),
|
||||||
|
'end' => array(
|
||||||
|
(int) date('Y', $end),
|
||||||
|
(int) date('n', $end),
|
||||||
|
(int) date('j', $end),
|
||||||
|
),
|
||||||
|
'link' => $this->helper->url->href('project', 'show', array('project_id' => $project['id'])),
|
||||||
|
'board_link' => $this->helper->url->href('board', 'show', array('project_id' => $project['id'])),
|
||||||
|
'gantt_link' => $this->helper->url->href('gantt', 'project', array('project_id' => $project['id'])),
|
||||||
|
'color' => $color,
|
||||||
|
'not_defined' => empty($project['start_date']) || empty($project['end_date']),
|
||||||
|
'users' => $this->projectPermission->getProjectUsers($project['id']),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $bars;
|
||||||
|
}
|
||||||
|
}
|
33
sources/app/Formatter/TaskFilterAutoCompleteFormatter.php
Normal file
33
sources/app/Formatter/TaskFilterAutoCompleteFormatter.php
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Formatter;
|
||||||
|
|
||||||
|
use Model\Task;
|
||||||
|
use Model\TaskFilter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Autocomplete formatter for task filter
|
||||||
|
*
|
||||||
|
* @package formatter
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class TaskFilterAutoCompleteFormatter extends TaskFilter implements FormatterInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Format the tasks for the ajax autocompletion
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function format()
|
||||||
|
{
|
||||||
|
$tasks = $this->query->columns(Task::TABLE.'.id', Task::TABLE.'.title')->findAll();
|
||||||
|
|
||||||
|
foreach ($tasks as &$task) {
|
||||||
|
$task['value'] = $task['title'];
|
||||||
|
$task['label'] = '#'.$task['id'].' - '.$task['title'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $tasks;
|
||||||
|
}
|
||||||
|
}
|
76
sources/app/Formatter/TaskFilterCalendarEvent.php
Normal file
76
sources/app/Formatter/TaskFilterCalendarEvent.php
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Formatter;
|
||||||
|
|
||||||
|
use Model\TaskFilter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common class to handle calendar events
|
||||||
|
*
|
||||||
|
* @package formatter
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
abstract class TaskFilterCalendarEvent extends TaskFilter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Column used for event start date
|
||||||
|
*
|
||||||
|
* @access protected
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $startColumn = 'date_started';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Column used for event end date
|
||||||
|
*
|
||||||
|
* @access protected
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $endColumn = 'date_completed';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Full day event flag
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
private $fullDay = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform results to calendar events
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $start_column Column name for the start date
|
||||||
|
* @param string $end_column Column name for the end date
|
||||||
|
* @return TaskFilterCalendarEvent
|
||||||
|
*/
|
||||||
|
public function setColumns($start_column, $end_column = '')
|
||||||
|
{
|
||||||
|
$this->startColumn = $start_column;
|
||||||
|
$this->endColumn = $end_column ?: $start_column;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When called calendar events will be full day
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return TaskFilterCalendarEvent
|
||||||
|
*/
|
||||||
|
public function setFullDay()
|
||||||
|
{
|
||||||
|
$this->fullDay = true;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the events are full day
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function isFullDay()
|
||||||
|
{
|
||||||
|
return $this->fullDay;
|
||||||
|
}
|
||||||
|
}
|
52
sources/app/Formatter/TaskFilterCalendarFormatter.php
Normal file
52
sources/app/Formatter/TaskFilterCalendarFormatter.php
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Formatter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calendar event formatter for task filter
|
||||||
|
*
|
||||||
|
* @package formatter
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class TaskFilterCalendarFormatter extends TaskFilterCalendarEvent implements FormatterInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Transform tasks to calendar events
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function format()
|
||||||
|
{
|
||||||
|
$events = array();
|
||||||
|
|
||||||
|
foreach ($this->query->findAll() as $task) {
|
||||||
|
$events[] = array(
|
||||||
|
'timezoneParam' => $this->config->getCurrentTimezone(),
|
||||||
|
'id' => $task['id'],
|
||||||
|
'title' => t('#%d', $task['id']).' '.$task['title'],
|
||||||
|
'backgroundColor' => $this->color->getBackgroundColor($task['color_id']),
|
||||||
|
'borderColor' => $this->color->getBorderColor($task['color_id']),
|
||||||
|
'textColor' => 'black',
|
||||||
|
'url' => $this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])),
|
||||||
|
'start' => date($this->getDateTimeFormat(), $task[$this->startColumn]),
|
||||||
|
'end' => date($this->getDateTimeFormat(), $task[$this->endColumn] ?: time()),
|
||||||
|
'editable' => $this->isFullDay(),
|
||||||
|
'allday' => $this->isFullDay(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $events;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get DateTime format for event
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function getDateTimeFormat()
|
||||||
|
{
|
||||||
|
return $this->isFullDay() ? 'Y-m-d' : 'Y-m-d\TH:i:s';
|
||||||
|
}
|
||||||
|
}
|
78
sources/app/Formatter/TaskFilterGanttFormatter.php
Normal file
78
sources/app/Formatter/TaskFilterGanttFormatter.php
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Formatter;
|
||||||
|
|
||||||
|
use Model\TaskFilter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gantt chart formatter for task filter
|
||||||
|
*
|
||||||
|
* @package formatter
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class TaskFilterGanttFormatter extends TaskFilter implements FormatterInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Local cache for project columns
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $columns = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format tasks to be displayed in the Gantt chart
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function format()
|
||||||
|
{
|
||||||
|
$bars = array();
|
||||||
|
|
||||||
|
foreach ($this->query->findAll() as $task) {
|
||||||
|
$bars[] = $this->formatTask($task);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $bars;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format a single task
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param array $task
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function formatTask(array $task)
|
||||||
|
{
|
||||||
|
if (! isset($this->columns[$task['project_id']])) {
|
||||||
|
$this->columns[$task['project_id']] = $this->board->getColumnsList($task['project_id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$start = $task['date_started'] ?: time();
|
||||||
|
$end = $task['date_due'] ?: $start;
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'type' => 'task',
|
||||||
|
'id' => $task['id'],
|
||||||
|
'title' => $task['title'],
|
||||||
|
'start' => array(
|
||||||
|
(int) date('Y', $start),
|
||||||
|
(int) date('n', $start),
|
||||||
|
(int) date('j', $start),
|
||||||
|
),
|
||||||
|
'end' => array(
|
||||||
|
(int) date('Y', $end),
|
||||||
|
(int) date('n', $end),
|
||||||
|
(int) date('j', $end),
|
||||||
|
),
|
||||||
|
'column_title' => $task['column_name'],
|
||||||
|
'assignee' => $task['assignee_name'] ?: $task['assignee_username'],
|
||||||
|
'progress' => $this->task->getProgress($task, $this->columns[$task['project_id']]).'%',
|
||||||
|
'link' => $this->helper->url->href('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])),
|
||||||
|
'color' => $this->color->getColorProperties($task['color_id']),
|
||||||
|
'not_defined' => empty($task['date_due']) || empty($task['date_started']),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
135
sources/app/Formatter/TaskFilterICalendarFormatter.php
Normal file
135
sources/app/Formatter/TaskFilterICalendarFormatter.php
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Formatter;
|
||||||
|
|
||||||
|
use DateTime;
|
||||||
|
use Eluceo\iCal\Component\Calendar;
|
||||||
|
use Eluceo\iCal\Component\Event;
|
||||||
|
use Eluceo\iCal\Property\Event\Attendees;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* iCal event formatter for task filter
|
||||||
|
*
|
||||||
|
* @package formatter
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class TaskFilterICalendarFormatter extends TaskFilterCalendarEvent implements FormatterInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Calendar object
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @var \Eluceo\iCal\Component\Calendar
|
||||||
|
*/
|
||||||
|
private $vCalendar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Ical events
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function format()
|
||||||
|
{
|
||||||
|
return $this->vCalendar->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set calendar object
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param \Eluceo\iCal\Component\Calendar $vCalendar
|
||||||
|
* @return TaskFilterICalendarFormatter
|
||||||
|
*/
|
||||||
|
public function setCalendar(Calendar $vCalendar)
|
||||||
|
{
|
||||||
|
$this->vCalendar = $vCalendar;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform results to ical events
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return TaskFilterICalendarFormatter
|
||||||
|
*/
|
||||||
|
public function addDateTimeEvents()
|
||||||
|
{
|
||||||
|
foreach ($this->query->findAll() as $task) {
|
||||||
|
|
||||||
|
$start = new DateTime;
|
||||||
|
$start->setTimestamp($task[$this->startColumn]);
|
||||||
|
|
||||||
|
$end = new DateTime;
|
||||||
|
$end->setTimestamp($task[$this->endColumn] ?: time());
|
||||||
|
|
||||||
|
$vEvent = $this->getTaskIcalEvent($task, 'task-#'.$task['id'].'-'.$this->startColumn.'-'.$this->endColumn);
|
||||||
|
$vEvent->setDtStart($start);
|
||||||
|
$vEvent->setDtEnd($end);
|
||||||
|
|
||||||
|
$this->vCalendar->addComponent($vEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform results to all day ical events
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return TaskFilterICalendarFormatter
|
||||||
|
*/
|
||||||
|
public function addFullDayEvents()
|
||||||
|
{
|
||||||
|
foreach ($this->query->findAll() as $task) {
|
||||||
|
|
||||||
|
$date = new DateTime;
|
||||||
|
$date->setTimestamp($task[$this->startColumn]);
|
||||||
|
|
||||||
|
$vEvent = $this->getTaskIcalEvent($task, 'task-#'.$task['id'].'-'.$this->startColumn);
|
||||||
|
$vEvent->setDtStart($date);
|
||||||
|
$vEvent->setDtEnd($date);
|
||||||
|
$vEvent->setNoTime(true);
|
||||||
|
|
||||||
|
$this->vCalendar->addComponent($vEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get common events for task ical events
|
||||||
|
*
|
||||||
|
* @access protected
|
||||||
|
* @param array $task
|
||||||
|
* @param string $uid
|
||||||
|
* @return Event
|
||||||
|
*/
|
||||||
|
protected function getTaskIcalEvent(array &$task, $uid)
|
||||||
|
{
|
||||||
|
$dateCreation = new DateTime;
|
||||||
|
$dateCreation->setTimestamp($task['date_creation']);
|
||||||
|
|
||||||
|
$dateModif = new DateTime;
|
||||||
|
$dateModif->setTimestamp($task['date_modification']);
|
||||||
|
|
||||||
|
$vEvent = new Event($uid);
|
||||||
|
$vEvent->setCreated($dateCreation);
|
||||||
|
$vEvent->setModified($dateModif);
|
||||||
|
$vEvent->setUseTimezone(true);
|
||||||
|
$vEvent->setSummary(t('#%d', $task['id']).' '.$task['title']);
|
||||||
|
$vEvent->setUrl($this->helper->url->base().$this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
|
||||||
|
|
||||||
|
if (! empty($task['owner_id'])) {
|
||||||
|
$vEvent->setOrganizer($task['assignee_name'] ?: $task['assignee_username'], $task['assignee_email']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! empty($task['creator_id'])) {
|
||||||
|
$attendees = new Attendees;
|
||||||
|
$attendees->add('MAILTO:'.($task['creator_email'] ?: $task['creator_username'].'@kanboard.local'));
|
||||||
|
$vEvent->setAttendees($attendees);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $vEvent;
|
||||||
|
}
|
||||||
|
}
|
|
@ -67,9 +67,11 @@ class App extends \Core\Base
|
||||||
if (isset($this->session['flash_message'])) {
|
if (isset($this->session['flash_message'])) {
|
||||||
$html = '<div class="alert alert-success alert-fade-out">'.$this->helper->e($this->session['flash_message']).'</div>';
|
$html = '<div class="alert alert-success alert-fade-out">'.$this->helper->e($this->session['flash_message']).'</div>';
|
||||||
unset($this->session['flash_message']);
|
unset($this->session['flash_message']);
|
||||||
|
unset($this->session['flash_error_message']);
|
||||||
}
|
}
|
||||||
else if (isset($this->session['flash_error_message'])) {
|
else if (isset($this->session['flash_error_message'])) {
|
||||||
$html = '<div class="alert alert-error">'.$this->helper->e($this->session['flash_error_message']).'</div>';
|
$html = '<div class="alert alert-error">'.$this->helper->e($this->session['flash_error_message']).'</div>';
|
||||||
|
unset($this->session['flash_message']);
|
||||||
unset($this->session['flash_error_message']);
|
unset($this->session['flash_error_message']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -103,6 +103,26 @@ class Form extends \Core\Base
|
||||||
return '<label><input type="radio" name="'.$name.'" class="'.$class.'" value="'.$this->helper->e($value).'" '.($selected ? 'checked="checked"' : '').'> '.$this->helper->e($label).'</label>';
|
return '<label><input type="radio" name="'.$name.'" class="'.$class.'" value="'.$this->helper->e($value).'" '.($selected ? 'checked="checked"' : '').'> '.$this->helper->e($label).'</label>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display a checkboxes group
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $name Field name
|
||||||
|
* @param array $options Options
|
||||||
|
* @param array $values Form values
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function checkboxes($name, array $options, array $values = array())
|
||||||
|
{
|
||||||
|
$html = '';
|
||||||
|
|
||||||
|
foreach ($options as $value => $label) {
|
||||||
|
$html .= $this->checkbox($name.'['.$value.']', $label, $value, isset($values[$name]) && in_array($value, $values[$name]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $html;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display a checkbox field
|
* Display a checkbox field
|
||||||
*
|
*
|
||||||
|
|
64
sources/app/Helper/Hook.php
Normal file
64
sources/app/Helper/Hook.php
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Helper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Template Hook helpers
|
||||||
|
*
|
||||||
|
* @package helper
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class Hook extends \Core\Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Add assets JS or CSS
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $type
|
||||||
|
* @param string $hook
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function asset($type, $hook)
|
||||||
|
{
|
||||||
|
$buffer = '';
|
||||||
|
|
||||||
|
foreach ($this->hook->getListeners($hook) as $file) {
|
||||||
|
$buffer .= $this->helper->asset->$type($file);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render all attached hooks
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $hook
|
||||||
|
* @param array $variables
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function render($hook, array $variables = array())
|
||||||
|
{
|
||||||
|
$buffer = '';
|
||||||
|
|
||||||
|
foreach ($this->hook->getListeners($hook) as $template) {
|
||||||
|
$buffer .= $this->template->render($template, $variables);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attach a template to a hook
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $hook
|
||||||
|
* @param string $template
|
||||||
|
* @return \Helper\Hook
|
||||||
|
*/
|
||||||
|
public function attach($hook, $template)
|
||||||
|
{
|
||||||
|
$this->hook->on($hook, $template);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,17 @@ namespace Helper;
|
||||||
*/
|
*/
|
||||||
class User extends \Core\Base
|
class User extends \Core\Base
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Return true if the logged user as unread notifications
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function hasNotifications()
|
||||||
|
{
|
||||||
|
return $this->webNotification->hasNotifications($this->userSession->getId());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get initials from a user
|
* Get initials from a user
|
||||||
*
|
*
|
||||||
|
@ -99,7 +110,7 @@ class User extends \Core\Base
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->memoryCache->proxy('acl', 'handleProjectAdminPermissions', $project_id);
|
return $this->memoryCache->proxy($this->container['acl'], 'handleProjectAdminPermissions', $project_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -114,7 +125,7 @@ class User extends \Core\Base
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->memoryCache->proxy('acl', 'handleProjectManagerPermissions', $project_id);
|
return $this->memoryCache->proxy($this->container['acl'], 'handleProjectManagerPermissions', $project_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
namespace Integration;
|
namespace Integration;
|
||||||
|
|
||||||
use HTML_To_Markdown;
|
|
||||||
use Core\Tool;
|
use Core\Tool;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -76,8 +75,7 @@ class Mailgun extends \Core\Base
|
||||||
|
|
||||||
// Get the Markdown contents
|
// Get the Markdown contents
|
||||||
if (! empty($payload['stripped-html'])) {
|
if (! empty($payload['stripped-html'])) {
|
||||||
$markdown = new HTML_To_Markdown($payload['stripped-html'], array('strip_tags' => true));
|
$description = $this->htmlConverter->convert($payload['stripped-html']);
|
||||||
$description = $markdown->output();
|
|
||||||
}
|
}
|
||||||
else if (! empty($payload['stripped-text'])) {
|
else if (! empty($payload['stripped-text'])) {
|
||||||
$description = $payload['stripped-text'];
|
$description = $payload['stripped-text'];
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
namespace Integration;
|
namespace Integration;
|
||||||
|
|
||||||
use HTML_To_Markdown;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Postmark integration
|
* Postmark integration
|
||||||
*
|
*
|
||||||
|
@ -76,8 +74,7 @@ class Postmark extends \Core\Base
|
||||||
|
|
||||||
// Get the Markdown contents
|
// Get the Markdown contents
|
||||||
if (! empty($payload['HtmlBody'])) {
|
if (! empty($payload['HtmlBody'])) {
|
||||||
$markdown = new HTML_To_Markdown($payload['HtmlBody'], array('strip_tags' => true));
|
$description = $this->htmlConverter->convert($payload['HtmlBody']);
|
||||||
$description = $markdown->output();
|
|
||||||
}
|
}
|
||||||
else if (! empty($payload['TextBody'])) {
|
else if (! empty($payload['TextBody'])) {
|
||||||
$description = $payload['TextBody'];
|
$description = $payload['TextBody'];
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
namespace Integration;
|
namespace Integration;
|
||||||
|
|
||||||
use HTML_To_Markdown;
|
|
||||||
use Core\Tool;
|
use Core\Tool;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -79,8 +78,7 @@ class Sendgrid extends \Core\Base
|
||||||
|
|
||||||
// Get the Markdown contents
|
// Get the Markdown contents
|
||||||
if (! empty($payload['html'])) {
|
if (! empty($payload['html'])) {
|
||||||
$markdown = new HTML_To_Markdown($payload['html'], array('strip_tags' => true));
|
$description = $this->htmlConverter->convert($payload['html']);
|
||||||
$description = $markdown->output();
|
|
||||||
}
|
}
|
||||||
else if (! empty($payload['text'])) {
|
else if (! empty($payload['text'])) {
|
||||||
$description = $payload['text'];
|
$description = $payload['text'];
|
||||||
|
|
|
@ -36,7 +36,7 @@ class SlackWebhook extends \Core\Base
|
||||||
}
|
}
|
||||||
|
|
||||||
$options = $this->projectIntegration->getParameters($project_id);
|
$options = $this->projectIntegration->getParameters($project_id);
|
||||||
return $options['slack_webhook_url'];
|
return isset($options['slack_webhook_url']) ? $options['slack_webhook_url'] : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -52,14 +52,14 @@ class SlackWebhook extends \Core\Base
|
||||||
|
|
||||||
if (! empty($channel)) {
|
if (! empty($channel)) {
|
||||||
return $channel;
|
return $channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
$options = $this->projectIntegration->getParameters($project_id);
|
$options = $this->projectIntegration->getParameters($project_id);
|
||||||
return $options['slack_webhook_channel'];
|
return isset($options['slack_webhook_channel']) ? $options['slack_webhook_channel'] : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send message to the incoming Slack webhook
|
* Send notification to Slack
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @param integer $project_id Project id
|
* @param integer $project_id Project id
|
||||||
|
@ -76,23 +76,52 @@ class SlackWebhook extends \Core\Base
|
||||||
$event['event_name'] = $event_name;
|
$event['event_name'] = $event_name;
|
||||||
$event['author'] = $this->user->getFullname($this->session['user']);
|
$event['author'] = $this->user->getFullname($this->session['user']);
|
||||||
|
|
||||||
$payload = array(
|
$message = '*['.$project['name'].']* ';
|
||||||
'text' => '*['.$project['name'].']* '.str_replace('"', '"', $this->projectActivity->getTitle($event)).(isset($event['task']['title']) ? ' ('.$event['task']['title'].')' : ''),
|
$message .= str_replace('"', '"', $this->projectActivity->getTitle($event));
|
||||||
'username' => 'Kanboard',
|
$message .= isset($event['task']['title']) ? ' ('.$event['task']['title'].')' : '';
|
||||||
'icon_url' => 'http://kanboard.net/assets/img/favicon.png',
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($this->config->get('application_url')) {
|
if ($this->config->get('application_url')) {
|
||||||
$payload['text'] .= ' - <'.$this->helper->url->href('task', 'show', array('task_id' => $task_id, 'project_id' => $project_id), false, '', true);
|
$message .= ' - <'.$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').'>';
|
$message .= '|'.t('view the task on Kanboard').'>';
|
||||||
}
|
}
|
||||||
|
|
||||||
$channel = $this->getChannel($project_id);
|
$this->sendMessage($project_id, $message);
|
||||||
if (! empty($channel)) {
|
|
||||||
$payload['channel'] = $channel;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->httpClient->postJson($this->getWebhookUrl($project_id), $payload);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send message to Slack
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $project_id
|
||||||
|
* @param string $message
|
||||||
|
*/
|
||||||
|
public function sendMessage($project_id, $message)
|
||||||
|
{
|
||||||
|
$payload = array(
|
||||||
|
'text' => $message,
|
||||||
|
'username' => 'Kanboard',
|
||||||
|
'icon_url' => 'http://kanboard.net/assets/img/favicon.png',
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->sendPayload($project_id, $payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send payload to Slack
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $project_id
|
||||||
|
* @param array $payload
|
||||||
|
*/
|
||||||
|
public function sendPayload($project_id, array $payload)
|
||||||
|
{
|
||||||
|
$channel = $this->getChannel($project_id);
|
||||||
|
|
||||||
|
if (! empty($channel)) {
|
||||||
|
$payload['channel'] = $channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->httpClient->postJson($this->getWebhookUrl($project_id), $payload);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -395,8 +395,6 @@ return array(
|
||||||
'Remote' => 'Vzdálený',
|
'Remote' => 'Vzdálený',
|
||||||
'Enabled' => 'Povoleno',
|
'Enabled' => 'Povoleno',
|
||||||
'Disabled' => 'Zakázáno',
|
'Disabled' => 'Zakázáno',
|
||||||
'Google account linked' => 'Google účet byl propojen',
|
|
||||||
'Github account linked' => 'Mit Githubaccount verbunden',
|
|
||||||
'Username:' => 'Uživatelské jméno:',
|
'Username:' => 'Uživatelské jméno:',
|
||||||
'Name:' => 'Jméno:',
|
'Name:' => 'Jméno:',
|
||||||
'Email:' => 'e-mail',
|
'Email:' => 'e-mail',
|
||||||
|
@ -667,75 +665,26 @@ return array(
|
||||||
'Horizontal scrolling' => 'Horizontální rolování',
|
'Horizontal scrolling' => 'Horizontální rolování',
|
||||||
'Compact/wide view' => 'Kompaktní/plné zobrazení',
|
'Compact/wide view' => 'Kompaktní/plné zobrazení',
|
||||||
'No results match:' => 'Žádná shoda:',
|
'No results match:' => 'Žádná shoda:',
|
||||||
'Remove hourly rate' => 'Stundensatz entfernen',
|
|
||||||
'Do you really want to remove this hourly rate?' => 'Opravdu chcete odstranit tuto hodinovou sazbu?',
|
|
||||||
'Hourly rates' => 'Hodinové sazby',
|
|
||||||
'Hourly rate' => 'Hodinová sazba',
|
|
||||||
'Currency' => 'Měna',
|
'Currency' => 'Měna',
|
||||||
'Effective date' => 'Datum účinnosti',
|
|
||||||
'Add new rate' => 'Přidat novou hodinovou sazbu',
|
|
||||||
'Rate removed successfully.' => 'Sazba byla úspěšně odstraněna',
|
|
||||||
'Unable to remove this rate.' => 'Sazbu nelze odstranit.',
|
|
||||||
'Unable to save the hourly rate.' => 'Hodinovou sazbu nelze uložit',
|
|
||||||
'Hourly rate created successfully.' => 'Hodinová sazba byla úspěšně vytvořena.',
|
|
||||||
'Start time' => 'Počáteční datum',
|
|
||||||
'End time' => 'Konečné datum',
|
|
||||||
'Comment' => 'Komentář',
|
|
||||||
'All day' => 'Všechny dny',
|
|
||||||
'Day' => 'Den',
|
|
||||||
'Manage timetable' => 'Spravovat pracovní dobu',
|
|
||||||
'Overtime timetable' => 'Přesčasy',
|
|
||||||
'Time off timetable' => 'Pracovní volno',
|
|
||||||
'Timetable' => 'Pracovní doba',
|
|
||||||
'Work timetable' => 'Pracovní doba',
|
|
||||||
'Week timetable' => 'Týdenní pracovní doba',
|
|
||||||
'Day timetable' => 'Denní pracovní doba',
|
|
||||||
'From' => 'Od',
|
|
||||||
'To' => 'Do',
|
|
||||||
'Time slot created successfully.' => 'Časový úsek byl úspěšně vytvořen.',
|
|
||||||
'Unable to save this time slot.' => 'Nelze uložit tento časový úsek.',
|
|
||||||
'Time slot removed successfully.' => 'Časový úsek byl odstraněn.',
|
|
||||||
'Unable to remove this time slot.' => 'Nelze odstranit tento časový úsek',
|
|
||||||
'Do you really want to remove this time slot?' => 'Opravdu chcete odstranit tento časový úsek?',
|
|
||||||
'Remove time slot' => 'Odstranit časový úsek',
|
|
||||||
'Add new time slot' => 'Přidat nový časový úsek',
|
|
||||||
'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => 'Tato pracovní doba se použije když je zaškrtnuto políčko "Celý den" pro plánovanou pracovní dobu i přesčas .',
|
|
||||||
'Files' => 'Soubory',
|
'Files' => 'Soubory',
|
||||||
'Images' => 'Obrázky',
|
'Images' => 'Obrázky',
|
||||||
'Private project' => 'Soukromý projekt',
|
'Private project' => 'Soukromý projekt',
|
||||||
'Amount' => 'Částka',
|
|
||||||
// 'AUD - Australian Dollar' => '',
|
// 'AUD - Australian Dollar' => '',
|
||||||
'Budget' => 'Rozpočet',
|
|
||||||
'Budget line' => 'Položka rozpočtu',
|
|
||||||
'Budget line removed successfully.' => 'Položka rozpočtu byla odstraněna',
|
|
||||||
'Budget lines' => 'Položky rozpočtu',
|
|
||||||
// 'CAD - Canadian Dollar' => '',
|
// 'CAD - Canadian Dollar' => '',
|
||||||
// 'CHF - Swiss Francs' => '',
|
// 'CHF - Swiss Francs' => '',
|
||||||
'Cost' => 'Cena',
|
|
||||||
'Cost breakdown' => 'Rozpis nákladů',
|
|
||||||
'Custom Stylesheet' => 'Vlastní šablony stylů',
|
'Custom Stylesheet' => 'Vlastní šablony stylů',
|
||||||
'download' => 'Stáhnout',
|
'download' => 'Stáhnout',
|
||||||
'Do you really want to remove this budget line?' => 'Opravdu chcete odstranit tuto rozpočtovou řádku?',
|
|
||||||
'EUR - Euro' => 'EUR - Euro',
|
'EUR - Euro' => 'EUR - Euro',
|
||||||
'Expenses' => 'Náklady',
|
|
||||||
'GBP - British Pound' => 'GBP - Britská Libra',
|
'GBP - British Pound' => 'GBP - Britská Libra',
|
||||||
'INR - Indian Rupee' => 'INR - Indische Rupien',
|
'INR - Indian Rupee' => 'INR - Indische Rupien',
|
||||||
'JPY - Japanese Yen' => 'JPY - Japanischer Yen',
|
'JPY - Japanese Yen' => 'JPY - Japanischer Yen',
|
||||||
'New budget line' => 'Nová položka rozpočtu',
|
|
||||||
'NZD - New Zealand Dollar' => 'NZD - Neuseeland-Dollar',
|
'NZD - New Zealand Dollar' => 'NZD - Neuseeland-Dollar',
|
||||||
'Remove a budget line' => 'Budgetlinie entfernen',
|
|
||||||
'Remove budget line' => 'Budgetlinie entfernen',
|
|
||||||
'RSD - Serbian dinar' => 'RSD - Serbische Dinar',
|
'RSD - Serbian dinar' => 'RSD - Serbische Dinar',
|
||||||
'The budget line have been created successfully.' => 'Položka rozpočtu byla úspěšně vytvořena.',
|
|
||||||
'Unable to create the budget line.' => 'Nelze vytvořit rozpočtovou řádku.',
|
|
||||||
'Unable to remove this budget line.' => 'Nelze vyjmout rozpočtovou řádku.',
|
|
||||||
'USD - US Dollar' => 'USD - US Dollar',
|
'USD - US Dollar' => 'USD - US Dollar',
|
||||||
'Remaining' => 'Zbývající',
|
|
||||||
'Destination column' => 'Cílový sloupec',
|
'Destination column' => 'Cílový sloupec',
|
||||||
'Move the task to another column when assigned to a user' => 'Přesunout úkol do jiného sloupce, když je úkol přiřazen uživateli.',
|
'Move the task to another column when assigned to a user' => 'Přesunout úkol do jiného sloupce, když je úkol přiřazen uživateli.',
|
||||||
'Move the task to another column when assignee is cleared' => 'Přesunout úkol do jiného sloupce, když je pověření uživatele vymazáno.',
|
'Move the task to another column when assignee is cleared' => 'Přesunout úkol do jiného sloupce, když je pověření uživatele vymazáno.',
|
||||||
'Source column' => 'Zdrojový sloupec',
|
'Source column' => 'Zdrojový sloupec',
|
||||||
// 'Show subtask estimates (forecast of future work)' => '',
|
|
||||||
'Transitions' => 'Změny etap',
|
'Transitions' => 'Změny etap',
|
||||||
'Executer' => 'Vykonavatel',
|
'Executer' => 'Vykonavatel',
|
||||||
'Time spent in the column' => 'Trvání jednotlivých etap',
|
'Time spent in the column' => 'Trvání jednotlivých etap',
|
||||||
|
@ -746,7 +695,6 @@ return array(
|
||||||
'Rate' => 'Kurz',
|
'Rate' => 'Kurz',
|
||||||
'Change reference currency' => 'Změnit referenční měnu',
|
'Change reference currency' => 'Změnit referenční měnu',
|
||||||
'Add a new currency rate' => 'Přidat nový směnný kurz',
|
'Add a new currency rate' => 'Přidat nový směnný kurz',
|
||||||
'Currency rates are used to calculate project budget.' => 'Měnové sazby se používají k výpočtu rozpočtu projektu.',
|
|
||||||
'Reference currency' => 'Referenční měna',
|
'Reference currency' => 'Referenční měna',
|
||||||
'The currency rate have been added successfully.' => 'Směnný kurz byl úspěšně přidán.',
|
'The currency rate have been added successfully.' => 'Směnný kurz byl úspěšně přidán.',
|
||||||
'Unable to add this currency rate.' => 'Nelze přidat tento směnný kurz',
|
'Unable to add this currency rate.' => 'Nelze přidat tento směnný kurz',
|
||||||
|
@ -878,9 +826,6 @@ 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 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',
|
'%s moved the task #%d to the swimlane "%s"' => '%s hat die Aufgabe #%d in die Swimlane "%s" verschoben',
|
||||||
// 'Swimlane' => '',
|
// 'Swimlane' => '',
|
||||||
'Budget overview' => 'Budget Übersicht',
|
|
||||||
'Type' => 'Typ',
|
|
||||||
'There is not enough data to show something.' => 'Es gibt nicht genug Daten für die Anzeige',
|
|
||||||
// 'Gravatar' => '',
|
// 'Gravatar' => '',
|
||||||
// 'Hipchat' => '',
|
// 'Hipchat' => '',
|
||||||
// 'Slack' => '',
|
// 'Slack' => '',
|
||||||
|
@ -1067,4 +1012,48 @@ return array(
|
||||||
// 'Table of contents' => '',
|
// 'Table of contents' => '',
|
||||||
// 'Gantt' => '',
|
// 'Gantt' => '',
|
||||||
// 'Help with project permissions' => '',
|
// 'Help with project permissions' => '',
|
||||||
|
// 'Author' => '',
|
||||||
|
// 'Version' => '',
|
||||||
|
// 'Plugins' => '',
|
||||||
|
// 'There is no plugin loaded.' => '',
|
||||||
|
// 'Set maximum column height' => '',
|
||||||
|
// 'Remove maximum column height' => '',
|
||||||
|
// 'My notifications' => '',
|
||||||
|
// 'Custom filters' => '',
|
||||||
|
// 'Your custom filter have been created successfully.' => '',
|
||||||
|
// 'Unable to create your custom filter.' => '',
|
||||||
|
// 'Custom filter removed successfully.' => '',
|
||||||
|
// 'Unable to remove this custom filter.' => '',
|
||||||
|
// 'Edit custom filter' => '',
|
||||||
|
// 'Your custom filter have been updated successfully.' => '',
|
||||||
|
// 'Unable to update custom filter.' => '',
|
||||||
|
// 'Web' => '',
|
||||||
|
// 'New attachment on task #%d: %s' => '',
|
||||||
|
// 'New comment on task #%d' => '',
|
||||||
|
// 'Comment updated on task #%d' => '',
|
||||||
|
// 'New subtask on task #%d' => '',
|
||||||
|
// 'Subtask updated on task #%d' => '',
|
||||||
|
// 'New task #%d: %s' => '',
|
||||||
|
// 'Task updated #%d' => '',
|
||||||
|
// 'Task #%d closed' => '',
|
||||||
|
// 'Task #%d opened' => '',
|
||||||
|
// 'Column changed for task #%d' => '',
|
||||||
|
// 'New position for task #%d' => '',
|
||||||
|
// 'Swimlane changed for task #%d' => '',
|
||||||
|
// 'Assignee changed on task #%d' => '',
|
||||||
|
// '%d overdue tasks' => '',
|
||||||
|
// 'Task #%d is overdue' => '',
|
||||||
|
// 'No new notifications.' => '',
|
||||||
|
// 'Mark all as read' => '',
|
||||||
|
// 'Mark as read' => '',
|
||||||
|
// 'Total number of tasks in this column across all swimlanes' => '',
|
||||||
|
// 'Collapse swimlane' => '',
|
||||||
|
// 'Expand swimlane' => '',
|
||||||
|
// 'Add a new filter' => '',
|
||||||
|
// 'Share with all project members' => '',
|
||||||
|
// 'Shared' => '',
|
||||||
|
// 'Owner' => '',
|
||||||
|
// 'Unread notifications' => '',
|
||||||
|
// 'My filters' => '',
|
||||||
|
// 'Notification methods:' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -395,8 +395,6 @@ return array(
|
||||||
'Remote' => 'Remote',
|
'Remote' => 'Remote',
|
||||||
'Enabled' => 'Aktiv',
|
'Enabled' => 'Aktiv',
|
||||||
'Disabled' => 'Deaktiveret',
|
'Disabled' => 'Deaktiveret',
|
||||||
'Google account linked' => 'Google-konto forbundet',
|
|
||||||
'Github account linked' => 'Github-konto forbundet',
|
|
||||||
'Username:' => 'Brugernavn',
|
'Username:' => 'Brugernavn',
|
||||||
'Name:' => 'Navn:',
|
'Name:' => 'Navn:',
|
||||||
'Email:' => 'Email:',
|
'Email:' => 'Email:',
|
||||||
|
@ -667,75 +665,26 @@ return array(
|
||||||
// 'Horizontal scrolling' => '',
|
// 'Horizontal scrolling' => '',
|
||||||
// 'Compact/wide view' => '',
|
// 'Compact/wide view' => '',
|
||||||
// 'No results match:' => '',
|
// 'No results match:' => '',
|
||||||
// 'Remove hourly rate' => '',
|
|
||||||
// 'Do you really want to remove this hourly rate?' => '',
|
|
||||||
// 'Hourly rates' => '',
|
|
||||||
// 'Hourly rate' => '',
|
|
||||||
// 'Currency' => '',
|
// 'Currency' => '',
|
||||||
// 'Effective date' => '',
|
|
||||||
// 'Add new rate' => '',
|
|
||||||
// 'Rate removed successfully.' => '',
|
|
||||||
// 'Unable to remove this rate.' => '',
|
|
||||||
// 'Unable to save the hourly rate.' => '',
|
|
||||||
// 'Hourly rate created successfully.' => '',
|
|
||||||
// 'Start time' => '',
|
|
||||||
// 'End time' => '',
|
|
||||||
// 'Comment' => '',
|
|
||||||
// 'All day' => '',
|
|
||||||
// 'Day' => '',
|
|
||||||
// 'Manage timetable' => '',
|
|
||||||
// 'Overtime timetable' => '',
|
|
||||||
// 'Time off timetable' => '',
|
|
||||||
// 'Timetable' => '',
|
|
||||||
// 'Work timetable' => '',
|
|
||||||
// 'Week timetable' => '',
|
|
||||||
// 'Day timetable' => '',
|
|
||||||
// 'From' => '',
|
|
||||||
// 'To' => '',
|
|
||||||
// 'Time slot created successfully.' => '',
|
|
||||||
// 'Unable to save this time slot.' => '',
|
|
||||||
// 'Time slot removed successfully.' => '',
|
|
||||||
// 'Unable to remove this time slot.' => '',
|
|
||||||
// 'Do you really want to remove this time slot?' => '',
|
|
||||||
// 'Remove time slot' => '',
|
|
||||||
// 'Add new time slot' => '',
|
|
||||||
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
|
|
||||||
// 'Files' => '',
|
// 'Files' => '',
|
||||||
// 'Images' => '',
|
// 'Images' => '',
|
||||||
// 'Private project' => '',
|
// 'Private project' => '',
|
||||||
// 'Amount' => '',
|
|
||||||
// 'AUD - Australian Dollar' => '',
|
// 'AUD - Australian Dollar' => '',
|
||||||
// 'Budget' => '',
|
|
||||||
// 'Budget line' => '',
|
|
||||||
// 'Budget line removed successfully.' => '',
|
|
||||||
// 'Budget lines' => '',
|
|
||||||
// 'CAD - Canadian Dollar' => '',
|
// 'CAD - Canadian Dollar' => '',
|
||||||
// 'CHF - Swiss Francs' => '',
|
// 'CHF - Swiss Francs' => '',
|
||||||
// 'Cost' => '',
|
|
||||||
// 'Cost breakdown' => '',
|
|
||||||
// 'Custom Stylesheet' => '',
|
// 'Custom Stylesheet' => '',
|
||||||
// 'download' => '',
|
// 'download' => '',
|
||||||
// 'Do you really want to remove this budget line?' => '',
|
|
||||||
// 'EUR - Euro' => '',
|
// 'EUR - Euro' => '',
|
||||||
// 'Expenses' => '',
|
|
||||||
// 'GBP - British Pound' => '',
|
// 'GBP - British Pound' => '',
|
||||||
// 'INR - Indian Rupee' => '',
|
// 'INR - Indian Rupee' => '',
|
||||||
// 'JPY - Japanese Yen' => '',
|
// 'JPY - Japanese Yen' => '',
|
||||||
// 'New budget line' => '',
|
|
||||||
// 'NZD - New Zealand Dollar' => '',
|
// 'NZD - New Zealand Dollar' => '',
|
||||||
// 'Remove a budget line' => '',
|
|
||||||
// 'Remove budget line' => '',
|
|
||||||
// 'RSD - Serbian dinar' => '',
|
// 'RSD - Serbian dinar' => '',
|
||||||
// 'The budget line have been created successfully.' => '',
|
|
||||||
// 'Unable to create the budget line.' => '',
|
|
||||||
// 'Unable to remove this budget line.' => '',
|
|
||||||
// 'USD - US Dollar' => '',
|
// 'USD - US Dollar' => '',
|
||||||
// 'Remaining' => '',
|
|
||||||
// 'Destination column' => '',
|
// 'Destination column' => '',
|
||||||
// 'Move the task to another column when assigned to a user' => '',
|
// 'Move the task to another column when assigned to a user' => '',
|
||||||
// 'Move the task to another column when assignee is cleared' => '',
|
// 'Move the task to another column when assignee is cleared' => '',
|
||||||
// 'Source column' => '',
|
// 'Source column' => '',
|
||||||
// 'Show subtask estimates (forecast of future work)' => '',
|
|
||||||
// 'Transitions' => '',
|
// 'Transitions' => '',
|
||||||
// 'Executer' => '',
|
// 'Executer' => '',
|
||||||
// 'Time spent in the column' => '',
|
// 'Time spent in the column' => '',
|
||||||
|
@ -746,7 +695,6 @@ return array(
|
||||||
// 'Rate' => '',
|
// 'Rate' => '',
|
||||||
// 'Change reference currency' => '',
|
// 'Change reference currency' => '',
|
||||||
// 'Add a new currency rate' => '',
|
// 'Add a new currency rate' => '',
|
||||||
// 'Currency rates are used to calculate project budget.' => '',
|
|
||||||
// 'Reference currency' => '',
|
// 'Reference currency' => '',
|
||||||
// 'The currency rate have been added successfully.' => '',
|
// 'The currency rate have been added successfully.' => '',
|
||||||
// 'Unable to add this currency rate.' => '',
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
@ -878,9 +826,6 @@ return array(
|
||||||
// '%s moved the task #%d to the first swimlane' => '',
|
// '%s moved the task #%d to the first swimlane' => '',
|
||||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||||
// 'Swimlane' => '',
|
// 'Swimlane' => '',
|
||||||
// 'Budget overview' => '',
|
|
||||||
// 'Type' => '',
|
|
||||||
// 'There is not enough data to show something.' => '',
|
|
||||||
// 'Gravatar' => '',
|
// 'Gravatar' => '',
|
||||||
// 'Hipchat' => '',
|
// 'Hipchat' => '',
|
||||||
// 'Slack' => '',
|
// 'Slack' => '',
|
||||||
|
@ -1067,4 +1012,48 @@ return array(
|
||||||
// 'Table of contents' => '',
|
// 'Table of contents' => '',
|
||||||
// 'Gantt' => '',
|
// 'Gantt' => '',
|
||||||
// 'Help with project permissions' => '',
|
// 'Help with project permissions' => '',
|
||||||
|
// 'Author' => '',
|
||||||
|
// 'Version' => '',
|
||||||
|
// 'Plugins' => '',
|
||||||
|
// 'There is no plugin loaded.' => '',
|
||||||
|
// 'Set maximum column height' => '',
|
||||||
|
// 'Remove maximum column height' => '',
|
||||||
|
// 'My notifications' => '',
|
||||||
|
// 'Custom filters' => '',
|
||||||
|
// 'Your custom filter have been created successfully.' => '',
|
||||||
|
// 'Unable to create your custom filter.' => '',
|
||||||
|
// 'Custom filter removed successfully.' => '',
|
||||||
|
// 'Unable to remove this custom filter.' => '',
|
||||||
|
// 'Edit custom filter' => '',
|
||||||
|
// 'Your custom filter have been updated successfully.' => '',
|
||||||
|
// 'Unable to update custom filter.' => '',
|
||||||
|
// 'Web' => '',
|
||||||
|
// 'New attachment on task #%d: %s' => '',
|
||||||
|
// 'New comment on task #%d' => '',
|
||||||
|
// 'Comment updated on task #%d' => '',
|
||||||
|
// 'New subtask on task #%d' => '',
|
||||||
|
// 'Subtask updated on task #%d' => '',
|
||||||
|
// 'New task #%d: %s' => '',
|
||||||
|
// 'Task updated #%d' => '',
|
||||||
|
// 'Task #%d closed' => '',
|
||||||
|
// 'Task #%d opened' => '',
|
||||||
|
// 'Column changed for task #%d' => '',
|
||||||
|
// 'New position for task #%d' => '',
|
||||||
|
// 'Swimlane changed for task #%d' => '',
|
||||||
|
// 'Assignee changed on task #%d' => '',
|
||||||
|
// '%d overdue tasks' => '',
|
||||||
|
// 'Task #%d is overdue' => '',
|
||||||
|
// 'No new notifications.' => '',
|
||||||
|
// 'Mark all as read' => '',
|
||||||
|
// 'Mark as read' => '',
|
||||||
|
// 'Total number of tasks in this column across all swimlanes' => '',
|
||||||
|
// 'Collapse swimlane' => '',
|
||||||
|
// 'Expand swimlane' => '',
|
||||||
|
// 'Add a new filter' => '',
|
||||||
|
// 'Share with all project members' => '',
|
||||||
|
// 'Shared' => '',
|
||||||
|
// 'Owner' => '',
|
||||||
|
// 'Unread notifications' => '',
|
||||||
|
// 'My filters' => '',
|
||||||
|
// 'Notification methods:' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -195,7 +195,7 @@ return array(
|
||||||
'Invalid date' => 'Ungültiges Datum',
|
'Invalid date' => 'Ungültiges Datum',
|
||||||
'Must be done before %B %e, %Y' => 'Muss vor dem %d.%m.%Y erledigt werden',
|
'Must be done before %B %e, %Y' => 'Muss vor dem %d.%m.%Y erledigt werden',
|
||||||
'%B %e, %Y' => '%d.%m.%Y',
|
'%B %e, %Y' => '%d.%m.%Y',
|
||||||
// '%b %e, %Y' => '',
|
'%b %e, %Y' => '%d.%m.%Y',
|
||||||
'Automatic actions' => 'Automatische Aktionen',
|
'Automatic actions' => 'Automatische Aktionen',
|
||||||
'Your automatic action have been created successfully.' => 'Die automatische Aktion wurde erfolgreich erstellt.',
|
'Your automatic action have been created successfully.' => 'Die automatische Aktion wurde erfolgreich erstellt.',
|
||||||
'Unable to create your automatic action.' => 'Erstellen der automatischen Aktion nicht möglich.',
|
'Unable to create your automatic action.' => 'Erstellen der automatischen Aktion nicht möglich.',
|
||||||
|
@ -263,10 +263,10 @@ return array(
|
||||||
'%d comments' => '%d Kommentare',
|
'%d comments' => '%d Kommentare',
|
||||||
'%d comment' => '%d Kommentar',
|
'%d comment' => '%d Kommentar',
|
||||||
'Email address invalid' => 'Ungültige E-Mail-Adresse',
|
'Email address invalid' => 'Ungültige E-Mail-Adresse',
|
||||||
// 'Your external account is not linked anymore to your profile.' => '',
|
'Your external account is not linked anymore to your profile.' => 'Dein externer Account ist nicht mehr mit deinem Profil verbunden.',
|
||||||
// 'Unable to unlink your external account.' => '',
|
'Unable to unlink your external account.' => 'Externer Account konnte nicht getrennt werden.',
|
||||||
// 'External authentication failed' => '',
|
'External authentication failed' => 'Externe Authentifizierung fehlgeschlagen',
|
||||||
// 'Your external account is linked to your profile successfully.' => '',
|
'Your external account is linked to your profile successfully.' => 'Dein externer Account wurde erfolgreich mit deinem Profil verbunden',
|
||||||
'Email' => 'E-Mail',
|
'Email' => 'E-Mail',
|
||||||
'Link my Google Account' => 'Verbinde meinen Google-Account',
|
'Link my Google Account' => 'Verbinde meinen Google-Account',
|
||||||
'Unlink my Google Account' => 'Verbindung mit meinem Google-Account trennen',
|
'Unlink my Google Account' => 'Verbindung mit meinem Google-Account trennen',
|
||||||
|
@ -395,8 +395,6 @@ return array(
|
||||||
'Remote' => 'Remote',
|
'Remote' => 'Remote',
|
||||||
'Enabled' => 'angeschaltet',
|
'Enabled' => 'angeschaltet',
|
||||||
'Disabled' => 'abgeschaltet',
|
'Disabled' => 'abgeschaltet',
|
||||||
'Google account linked' => 'Mit Google-Account verbunden',
|
|
||||||
'Github account linked' => 'Mit Github-Account verbunden',
|
|
||||||
'Username:' => 'Benutzername',
|
'Username:' => 'Benutzername',
|
||||||
'Name:' => 'Name',
|
'Name:' => 'Name',
|
||||||
'Email:' => 'E-Mail',
|
'Email:' => 'E-Mail',
|
||||||
|
@ -608,7 +606,7 @@ return array(
|
||||||
'Time Tracking' => 'Zeiterfassung',
|
'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?',
|
'Which parts of the project do you want to duplicate?' => 'Welcher Teil des Projekts soll kopiert werden?',
|
||||||
// 'Disallow login form' => '',
|
'Disallow login form' => 'Verbiete Login-Formular',
|
||||||
'Bitbucket commit received' => 'Bitbucket-Commit erhalten',
|
'Bitbucket commit received' => 'Bitbucket-Commit erhalten',
|
||||||
'Bitbucket webhooks' => 'Bitbucket-Webhooks',
|
'Bitbucket webhooks' => 'Bitbucket-Webhooks',
|
||||||
'Help on Bitbucket webhooks' => 'Hilfe für Bitbucket-Webhooks',
|
'Help on Bitbucket webhooks' => 'Hilfe für Bitbucket-Webhooks',
|
||||||
|
@ -667,75 +665,26 @@ return array(
|
||||||
'Horizontal scrolling' => 'Horizontales Scrollen',
|
'Horizontal scrolling' => 'Horizontales Scrollen',
|
||||||
'Compact/wide view' => 'Kompakt/Breite-Ansicht',
|
'Compact/wide view' => 'Kompakt/Breite-Ansicht',
|
||||||
'No results match:' => 'Keine Ergebnisse:',
|
'No results match:' => 'Keine Ergebnisse:',
|
||||||
'Remove hourly rate' => 'Stundensatz entfernen',
|
|
||||||
'Do you really want to remove this hourly rate?' => 'Diesen Stundensatz wirklich entfernen?',
|
|
||||||
'Hourly rates' => 'Stundensätze',
|
|
||||||
'Hourly rate' => 'Stundensatz',
|
|
||||||
'Currency' => 'Währung',
|
'Currency' => 'Währung',
|
||||||
'Effective date' => 'Inkraftsetzung',
|
|
||||||
'Add new rate' => 'Neue Rate hinzufügen',
|
|
||||||
'Rate removed successfully.' => 'Rate erfolgreich entfernt',
|
|
||||||
'Unable to remove this rate.' => 'Nicht in der Lage, diese Rate zu entfernen.',
|
|
||||||
'Unable to save the hourly rate.' => 'Nicht in der Lage, diese Rate zu speichern',
|
|
||||||
'Hourly rate created successfully.' => 'Stundensatz erfolgreich angelegt.',
|
|
||||||
'Start time' => 'Startzeit',
|
|
||||||
'End time' => 'Endzeit',
|
|
||||||
'Comment' => 'Kommentar',
|
|
||||||
'All day' => 'ganztägig',
|
|
||||||
'Day' => 'Tag',
|
|
||||||
'Manage timetable' => 'Zeitplan verwalten',
|
|
||||||
'Overtime timetable' => 'Überstunden Zeitplan',
|
|
||||||
'Time off timetable' => 'Freizeit Zeitplan',
|
|
||||||
'Timetable' => 'Zeitplan',
|
|
||||||
'Work timetable' => 'Arbeitszeitplan',
|
|
||||||
'Week timetable' => 'Wochenzeitplan',
|
|
||||||
'Day timetable' => 'Tageszeitplan',
|
|
||||||
'From' => 'von',
|
|
||||||
'To' => 'bis',
|
|
||||||
'Time slot created successfully.' => 'Zeitfenster erfolgreich erstellt.',
|
|
||||||
'Unable to save this time slot.' => 'Nicht in der Lage, dieses Zeitfenster zu speichern.',
|
|
||||||
'Time slot removed successfully.' => 'Zeitfenster erfolgreich entfernt.',
|
|
||||||
'Unable to remove this time slot.' => 'Nicht in der Lage, dieses Zeitfenster zu entfernen',
|
|
||||||
'Do you really want to remove this time slot?' => 'Soll diese Zeitfenster wirklich gelöscht werden?',
|
|
||||||
'Remove time slot' => 'Zeitfenster entfernen',
|
|
||||||
'Add new time slot' => 'Neues Zeitfenster hinzufügen',
|
|
||||||
'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => 'Dieses Zeitfenster wird verwendet, wenn die Checkbox "ganztägig" für Freizeit und Überstunden angeklickt ist.',
|
|
||||||
'Files' => 'Dateien',
|
'Files' => 'Dateien',
|
||||||
'Images' => 'Bilder',
|
'Images' => 'Bilder',
|
||||||
'Private project' => 'privates Projekt',
|
'Private project' => 'privates Projekt',
|
||||||
'Amount' => 'Betrag',
|
|
||||||
'AUD - Australian Dollar' => 'AUD - Australische 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' => 'CAD - Kanadische Dollar',
|
'CAD - Canadian Dollar' => 'CAD - Kanadische Dollar',
|
||||||
'CHF - Swiss Francs' => 'CHF - Schweizer Franken',
|
'CHF - Swiss Francs' => 'CHF - Schweizer Franken',
|
||||||
'Cost' => 'Kosten',
|
|
||||||
'Cost breakdown' => 'Kostenaufschlüsselung',
|
|
||||||
'Custom Stylesheet' => 'benutzerdefiniertes Stylesheet',
|
'Custom Stylesheet' => 'benutzerdefiniertes Stylesheet',
|
||||||
'download' => 'Download',
|
'download' => 'Download',
|
||||||
'Do you really want to remove this budget line?' => 'Soll diese Budgetlinie wirklich entfernt werden?',
|
|
||||||
'EUR - Euro' => 'EUR - Euro',
|
'EUR - Euro' => 'EUR - Euro',
|
||||||
'Expenses' => 'Kosten',
|
|
||||||
'GBP - British Pound' => 'GBP - Britische Pfund',
|
'GBP - British Pound' => 'GBP - Britische Pfund',
|
||||||
'INR - Indian Rupee' => 'INR - Indische Rupien',
|
'INR - Indian Rupee' => 'INR - Indische Rupien',
|
||||||
'JPY - Japanese Yen' => 'JPY - Japanische Yen',
|
'JPY - Japanese Yen' => 'JPY - Japanische Yen',
|
||||||
'New budget line' => 'Neue Budgetlinie',
|
|
||||||
'NZD - New Zealand Dollar' => 'NZD - Neuseeland-Dollar',
|
'NZD - New Zealand Dollar' => 'NZD - Neuseeland-Dollar',
|
||||||
'Remove a budget line' => 'Budgetlinie entfernen',
|
|
||||||
'Remove budget line' => 'Budgetlinie entfernen',
|
|
||||||
'RSD - Serbian dinar' => 'RSD - Serbische Dinar',
|
'RSD - Serbian dinar' => 'RSD - Serbische Dinar',
|
||||||
'The budget line have been created successfully.' => 'Die Budgetlinie wurde erfolgreich angelegt.',
|
|
||||||
'Unable to create the budget line.' => 'Budgetlinie konnte nicht erstellt werden.',
|
|
||||||
'Unable to remove this budget line.' => 'Budgetlinie konnte nicht gelöscht werden.',
|
|
||||||
'USD - US Dollar' => 'USD - US-Dollar',
|
'USD - US Dollar' => 'USD - US-Dollar',
|
||||||
'Remaining' => 'Verbleibend',
|
|
||||||
'Destination column' => 'Zielspalte',
|
'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 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.',
|
'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',
|
'Source column' => 'Quellspalte',
|
||||||
'Show subtask estimates (forecast of future work)' => 'Teilaufgaben-Schätzungen anzeigen (Prognose)',
|
|
||||||
'Transitions' => 'Übergänge',
|
'Transitions' => 'Übergänge',
|
||||||
'Executer' => 'Ausführender',
|
'Executer' => 'Ausführender',
|
||||||
'Time spent in the column' => 'Zeit in Spalte verbracht',
|
'Time spent in the column' => 'Zeit in Spalte verbracht',
|
||||||
|
@ -746,7 +695,6 @@ return array(
|
||||||
'Rate' => 'Kurse',
|
'Rate' => 'Kurse',
|
||||||
'Change reference currency' => 'Referenzwährung ändern',
|
'Change reference currency' => 'Referenzwährung ändern',
|
||||||
'Add a new currency rate' => 'Neuen Währungskurs hinzufügen',
|
'Add a new currency rate' => 'Neuen Währungskurs hinzufügen',
|
||||||
'Currency rates are used to calculate project budget.' => 'Währungskurse werden verwendet, um das Projektbudget zu berechnen.',
|
|
||||||
'Reference currency' => 'Referenzwährung',
|
'Reference currency' => 'Referenzwährung',
|
||||||
'The currency rate have been added successfully.' => 'Der Währungskurs wurde erfolgreich hinzugefügt.',
|
'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',
|
'Unable to add this currency rate.' => 'Währungskurs konnte nicht hinzugefügt werden',
|
||||||
|
@ -777,8 +725,8 @@ return array(
|
||||||
'uploaded by: %s' => 'Hochgeladen von: %s',
|
'uploaded by: %s' => 'Hochgeladen von: %s',
|
||||||
'uploaded on: %s' => 'Hochgeladen am: %s',
|
'uploaded on: %s' => 'Hochgeladen am: %s',
|
||||||
'size: %s' => 'Größe: %s',
|
'size: %s' => 'Größe: %s',
|
||||||
'Burndown chart for "%s"' => 'Burndown-Chart für "%s"',
|
'Burndown chart for "%s"' => 'Burndown-Diagramm für "%s"',
|
||||||
'Burndown chart' => 'Burndown-Chart',
|
'Burndown chart' => 'Burndown-Diagramm',
|
||||||
'This chart show the task complexity over the time (Work Remaining).' => 'Dieses Diagramm zeigt die Aufgabenkomplexität über den Faktor Zeit (Verbleibende Arbeit).',
|
'This chart show the task complexity over the time (Work Remaining).' => 'Dieses Diagramm zeigt die Aufgabenkomplexität über den Faktor Zeit (Verbleibende Arbeit).',
|
||||||
'Screenshot taken %s' => 'Screenshot aufgenommen %s ',
|
'Screenshot taken %s' => 'Screenshot aufgenommen %s ',
|
||||||
'Add a screenshot' => 'Füge einen Screenshot hinzu',
|
'Add a screenshot' => 'Füge einen Screenshot hinzu',
|
||||||
|
@ -827,7 +775,7 @@ return array(
|
||||||
'When task is moved from first column' => 'Wenn Aufgabe von erster Spalte verschoben wird',
|
'When task is moved from first column' => 'Wenn Aufgabe von erster Spalte verschoben wird',
|
||||||
'When task is moved to last column' => 'Wenn Aufgabe in letzte Spalte verschoben wird',
|
'When task is moved to last column' => 'Wenn Aufgabe in letzte Spalte verschoben wird',
|
||||||
'Year(s)' => 'Jahr(e)',
|
'Year(s)' => 'Jahr(e)',
|
||||||
// 'Jabber (XMPP)' => '',
|
'Jabber (XMPP)' => 'Jabber (XMPP)',
|
||||||
'Send notifications to Jabber' => 'Benachrichtigungen an Jabber senden',
|
'Send notifications to Jabber' => 'Benachrichtigungen an Jabber senden',
|
||||||
'XMPP server address' => 'XMPP-Server-Adresse',
|
'XMPP server address' => 'XMPP-Server-Adresse',
|
||||||
'Jabber domain' => 'Jabber-Domain',
|
'Jabber domain' => 'Jabber-Domain',
|
||||||
|
@ -844,7 +792,7 @@ return array(
|
||||||
'Subtasks time tracking' => 'Teilaufgaben-Zeiterfassung',
|
'Subtasks time tracking' => 'Teilaufgaben-Zeiterfassung',
|
||||||
'User calendar view' => 'Benutzer-Kalendersicht',
|
'User calendar view' => 'Benutzer-Kalendersicht',
|
||||||
'Automatically update the start date' => 'Beginndatum automatisch aktualisieren',
|
'Automatically update the start date' => 'Beginndatum automatisch aktualisieren',
|
||||||
// 'iCal feed' => '',
|
'iCal feed' => 'iCal Feed',
|
||||||
'Preferences' => 'Einstellungen',
|
'Preferences' => 'Einstellungen',
|
||||||
'Security' => 'Sicherheit',
|
'Security' => 'Sicherheit',
|
||||||
'Two factor authentication disabled' => 'Zwei-Faktor-Authentifizierung deaktiviert',
|
'Two factor authentication disabled' => 'Zwei-Faktor-Authentifizierung deaktiviert',
|
||||||
|
@ -854,21 +802,21 @@ return array(
|
||||||
'User that will receive the email' => 'Empfänger der E-Mail',
|
'User that will receive the email' => 'Empfänger der E-Mail',
|
||||||
'Email subject' => 'E-Mail-Betreff',
|
'Email subject' => 'E-Mail-Betreff',
|
||||||
'Date' => 'Datum',
|
'Date' => 'Datum',
|
||||||
// 'By @%s on Bitbucket' => '',
|
'By @%s on Bitbucket' => 'Durch @%s auf Bitbucket',
|
||||||
'Bitbucket Issue' => 'Bitbucket-Issue',
|
'Bitbucket Issue' => 'Bitbucket-Issue',
|
||||||
// 'Commit made by @%s on Bitbucket' => '',
|
'Commit made by @%s on Bitbucket' => 'Commit von @%s auf Bitbucket',
|
||||||
// 'Commit made by @%s on Github' => '',
|
'Commit made by @%s on Github' => 'Commit von @%s auf Github',
|
||||||
// 'By @%s on Github' => '',
|
'By @%s on Github' => 'Durch @%s auf Github',
|
||||||
// 'Commit made by @%s on Gitlab' => '',
|
'Commit made by @%s on Gitlab' => 'Commit von @%s auf Gitlab',
|
||||||
'Add a comment log when moving the task between columns' => 'Kommentar hinzufügen, wenn Aufgabe in andere Spalte verschoben wird',
|
'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',
|
'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',
|
'Send a task by email to someone' => 'Aufgabe per E-Mail versenden',
|
||||||
'Reopen a task' => 'Aufgabe wieder öffnen',
|
'Reopen a task' => 'Aufgabe wieder öffnen',
|
||||||
// 'Bitbucket issue opened' => '',
|
'Bitbucket issue opened' => 'Bitbucket Ticket eröffnet',
|
||||||
// 'Bitbucket issue closed' => '',
|
'Bitbucket issue closed' => 'Bitbucket Ticket geschlossen',
|
||||||
// 'Bitbucket issue reopened' => '',
|
'Bitbucket issue reopened' => 'Bitbucket Ticket wieder eröffnet',
|
||||||
// 'Bitbucket issue assignee change' => '',
|
'Bitbucket issue assignee change' => 'Bitbucket Ticket Zuordnung geändert',
|
||||||
// 'Bitbucket issue comment created' => '',
|
'Bitbucket issue comment created' => 'Bitbucket Ticket Kommentar erstellt',
|
||||||
'Column change' => 'Spalte geändert',
|
'Column change' => 'Spalte geändert',
|
||||||
'Position change' => 'Position geändert',
|
'Position change' => 'Position geändert',
|
||||||
'Swimlane change' => 'Swimlane geändert',
|
'Swimlane change' => 'Swimlane geändert',
|
||||||
|
@ -877,13 +825,10 @@ return array(
|
||||||
'Notification' => 'Benachrichtigungen',
|
'Notification' => 'Benachrichtigungen',
|
||||||
'%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 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',
|
'%s moved the task #%d to the swimlane "%s"' => '%s hat die Aufgabe #%d in die Swimlane "%s" verschoben',
|
||||||
// 'Swimlane' => '',
|
'Swimlane' => 'Swimlane',
|
||||||
'Budget overview' => 'Budget-Übersicht',
|
'Gravatar' => 'Gravatar',
|
||||||
'Type' => 'Typ',
|
'Hipchat' => 'Hipchat',
|
||||||
'There is not enough data to show something.' => 'Es gibt nicht genügend Daten für diese Anzeige',
|
'Slack' => 'Slack',
|
||||||
// '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 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',
|
'%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 gewählten Zeitraum',
|
'This report contains all subtasks information for the given date range.' => 'Der Bericht beinhaltet alle Teilaufgaben im gewählten Zeitraum',
|
||||||
|
@ -908,22 +853,22 @@ return array(
|
||||||
'The field "%s" have been updated' => 'Das Feld "%s" wurde verändert',
|
'The field "%s" have been updated' => 'Das Feld "%s" wurde verändert',
|
||||||
'The description have been modified' => 'Die Beschreibung wurde geändert',
|
'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)',
|
'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' => '',
|
'Swimlane: %s' => 'Swimlane: %s',
|
||||||
'I want to receive notifications for:' => 'Ich möchte Benachrichtigungen erhalten für:',
|
'I want to receive notifications for:' => 'Ich möchte Benachrichtigungen erhalten für:',
|
||||||
'All tasks' => 'Alle Aufgaben',
|
'All tasks' => 'Alle Aufgaben',
|
||||||
'Only for tasks assigned to me' => 'nur mir zugeordnete Aufgane',
|
'Only for tasks assigned to me' => 'nur mir zugeordnete Aufgane',
|
||||||
'Only for tasks created by me' => 'nur von mir erstellte Aufgaben',
|
'Only for tasks created by me' => 'nur von mir erstellte Aufgaben',
|
||||||
'Only for tasks created by me and assigned to me' => 'nur mir zugeordnete und von mir erstellte Aufgaben',
|
'Only for tasks created by me and assigned to me' => 'nur mir zugeordnete und von mir erstellte Aufgaben',
|
||||||
// '%A' => '',
|
'%A' => '%A',
|
||||||
// '%b %e, %Y, %k:%M %p' => '',
|
'%b %e, %Y, %k:%M %p' => '%b %e, %Y, %k:%M %p',
|
||||||
'New due date: %B %e, %Y' => 'Neues Ablaufdatum: %B %e, %Y',
|
'New due date: %B %e, %Y' => 'Neues Ablaufdatum: %B %e, %Y',
|
||||||
'Start date changed: %B %e, %Y' => 'Neues Beginndatum: %B %e, %Y',
|
'Start date changed: %B %e, %Y' => 'Neues Beginndatum: %B %e, %Y',
|
||||||
// '%k:%M %p' => '',
|
'%k:%M %p' => '%k:%M %p',
|
||||||
// '%%Y-%%m-%%d' => '',
|
'%%Y-%%m-%%d' => '%%d.%%m.%%Y',
|
||||||
'Total for all columns' => 'Gesamt für alle Spalten',
|
'Total for all columns' => 'Gesamt für alle Spalten',
|
||||||
'You need at least 2 days of data to show the chart.' => 'Es werden mindestens 2 Tage zur Darstellung benötigt',
|
'You need at least 2 days of data to show the chart.' => 'Es werden mindestens 2 Tage zur Darstellung benötigt',
|
||||||
// '<15m' => '',
|
'<15m' => '<15min',
|
||||||
// '<30m' => '',
|
'<30m' => '<30min',
|
||||||
'Stop timer' => 'Stoppe Timer',
|
'Stop timer' => 'Stoppe Timer',
|
||||||
'Start timer' => 'Starte Timer',
|
'Start timer' => 'Starte Timer',
|
||||||
'Add project member' => 'Projektmitglied hinzufügen',
|
'Add project member' => 'Projektmitglied hinzufügen',
|
||||||
|
@ -943,7 +888,7 @@ return array(
|
||||||
'Not assigned' => 'Nicht zugewiesen',
|
'Not assigned' => 'Nicht zugewiesen',
|
||||||
'View advanced search syntax' => 'Zur erweiterten Suchsyntax',
|
'View advanced search syntax' => 'Zur erweiterten Suchsyntax',
|
||||||
'Overview' => 'Überblick',
|
'Overview' => 'Überblick',
|
||||||
// '%b %e %Y' => '',
|
'%b %e %Y' => '%b %e %Y',
|
||||||
'Board/Calendar/List view' => 'Board-/Kalender-/Listen-Ansicht',
|
'Board/Calendar/List view' => 'Board-/Kalender-/Listen-Ansicht',
|
||||||
'Switch to the board view' => 'Zur Board-Ansicht',
|
'Switch to the board view' => 'Zur Board-Ansicht',
|
||||||
'Switch to the calendar view' => 'Zur Kalender-Ansicht',
|
'Switch to the calendar view' => 'Zur Kalender-Ansicht',
|
||||||
|
@ -963,108 +908,152 @@ return array(
|
||||||
'Search by category: ' => 'Suche nach Kategorie: ',
|
'Search by category: ' => 'Suche nach Kategorie: ',
|
||||||
'Search by description: ' => 'Suche nach Beschreibung: ',
|
'Search by description: ' => 'Suche nach Beschreibung: ',
|
||||||
'Search by due date: ' => 'Suche nach Fälligkeitsdatum: ',
|
'Search by due date: ' => 'Suche nach Fälligkeitsdatum: ',
|
||||||
// 'Lead and Cycle time for "%s"' => '',
|
'Lead and Cycle time for "%s"' => 'Durchlauf und Zykluszeit für "%s"',
|
||||||
// 'Average time spent into each column for "%s"' => '',
|
'Average time spent into each column for "%s"' => 'Durchschnittliche Zeit in jeder Spalte für "%s"',
|
||||||
// 'Average time spent into each column' => '',
|
'Average time spent into each column' => 'Durchschnittszeit in jeder Spalte',
|
||||||
// 'Average time spent' => '',
|
'Average time spent' => 'Durchschnittlicher Zeitverbrauch',
|
||||||
// 'This chart show the average time spent into each column for the last %d tasks.' => '',
|
'This chart show the average time spent into each column for the last %d tasks.' => 'Dieses Diagramm zeigt die durchschnittliche Zeit in jeder Spalte der letzten %d Aufgaben.',
|
||||||
// 'Average Lead and Cycle time' => '',
|
'Average Lead and Cycle time' => 'Durchschnittliche Zyklus- und Durchlaufzeit',
|
||||||
// 'Average lead time: ' => '',
|
'Average lead time: ' => 'Durchschnittliche Durchlaufzeit:',
|
||||||
// 'Average cycle time: ' => '',
|
'Average cycle time: ' => 'Durchschnittliche Zykluszeit:',
|
||||||
// 'Cycle Time' => '',
|
'Cycle Time' => 'Zykluszeit',
|
||||||
// 'Lead Time' => '',
|
'Lead Time' => 'Durchlaufzeit',
|
||||||
// 'This chart show the average lead and cycle time for the last %d tasks over the time.' => '',
|
'This chart show the average lead and cycle time for the last %d tasks over the time.' => 'Das Diagramm zeigt die durchschnittliche Durchlauf- und Zykluszeit der letzten %d Aufgaben über die Zeit an.',
|
||||||
// 'Average time into each column' => '',
|
'Average time into each column' => 'Durchschnittzeit in jeder Spalte',
|
||||||
// 'Lead and cycle time' => '',
|
'Lead and cycle time' => 'Durchlauf- und Zykluszeit',
|
||||||
// 'Google Authentication' => '',
|
'Google Authentication' => 'Google-Authentifizierung',
|
||||||
// 'Help on Google authentication' => '',
|
'Help on Google authentication' => 'Hilfe bei Google-Authentifizierung',
|
||||||
// 'Github Authentication' => '',
|
'Github Authentication' => 'Github-Authentifizierung',
|
||||||
// 'Help on Github authentication' => '',
|
'Help on Github authentication' => 'Hilfe bei Github-Authentifizierung',
|
||||||
// 'Channel/Group/User (Optional)' => '',
|
'Channel/Group/User (Optional)' => 'Kanal/Gruppe/Benutzer (optional)',
|
||||||
// 'Lead time: ' => '',
|
'Lead time: ' => 'Durchlaufzeit:',
|
||||||
// 'Cycle time: ' => '',
|
'Cycle time: ' => 'Zykluszeit:',
|
||||||
// 'Time spent into each column' => '',
|
'Time spent into each column' => 'zeit verbracht in jeder Spalte',
|
||||||
// 'The lead time is the duration between the task creation and the completion.' => '',
|
'The lead time is the duration between the task creation and the completion.' => 'Die Durchlaufzeit ist die Dauer zwischen Erstellung und Fertigstellung.',
|
||||||
// 'The cycle time is the duration between the start date and the completion.' => '',
|
'The cycle time is the duration between the start date and the completion.' => 'Die Zykluszeit ist die Dauer zwischen Start und Fertigstellung.',
|
||||||
// 'If the task is not closed the current time is used instead of the completion date.' => '',
|
'If the task is not closed the current time is used instead of the completion date.' => 'Wenn die Aufgabe nicht geschlossen ist, wird die aktuelle Zeit statt der Fertigstellung verwendet.',
|
||||||
// 'Set automatically the start date' => '',
|
'Set automatically the start date' => 'Setze Startdatum automatisch',
|
||||||
// 'Edit Authentication' => '',
|
'Edit Authentication' => 'Authentifizierung bearbeiten',
|
||||||
// 'Google Id' => '',
|
'Google Id' => 'Google Id',
|
||||||
// 'Github Id' => '',
|
'Github Id' => 'Github Id',
|
||||||
// 'Remote user' => '',
|
'Remote user' => 'Remote-Benutzer',
|
||||||
// 'Remote users do not store their password in Kanboard database, examples: LDAP, Google and Github accounts.' => '',
|
'Remote users do not store their password in Kanboard database, examples: LDAP, Google and Github accounts.' => 'Remote-Benutzer haben kein Passwort in der Kanboard Datenbank, Beispiel LDAP, Goole und Github Accounts',
|
||||||
// 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '',
|
'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => 'Wenn die Box "Verbiete Login-Formular" angeschaltet ist, werden Eingaben in das Login Formular ignoriert.',
|
||||||
// 'By @%s on Gitlab' => '',
|
'By @%s on Gitlab' => 'Durch @%s auf Gitlab',
|
||||||
// 'Gitlab issue comment created' => '',
|
'Gitlab issue comment created' => 'Gitlab Ticket Kommentar erstellt',
|
||||||
// 'New remote user' => '',
|
'New remote user' => 'Neuer Remote-Benutzer',
|
||||||
// 'New local user' => '',
|
'New local user' => 'Neuer lokaler Benutzer',
|
||||||
// 'Default task color' => '',
|
'Default task color' => 'Voreingestellte Aufgabenfarbe',
|
||||||
// 'Hide sidebar' => '',
|
'Hide sidebar' => 'Seitenleiste verstecken',
|
||||||
// 'Expand sidebar' => '',
|
'Expand sidebar' => 'Seitenleiste ausklappen',
|
||||||
// 'This feature does not work with all browsers.' => '',
|
'This feature does not work with all browsers.' => 'Diese Funktion funktioniert nicht mit allen Browsern',
|
||||||
// 'There is no destination project available.' => '',
|
'There is no destination project available.' => 'Es ist kein Zielprojekt vorhanden.',
|
||||||
// 'Trigger automatically subtask time tracking' => '',
|
'Trigger automatically subtask time tracking' => 'Teilaufgaben Zeiterfassung automatisch starten',
|
||||||
// 'Include closed tasks in the cumulative flow diagram' => '',
|
'Include closed tasks in the cumulative flow diagram' => 'Geschlossen Aufgaben ins kumulative Flussdiagramm einschließen',
|
||||||
// 'Current swimlane: %s' => '',
|
'Current swimlane: %s' => 'Aktuelle Swimlane: %s',
|
||||||
// 'Current column: %s' => '',
|
'Current column: %s' => 'Aktuelle Spalte: %s',
|
||||||
// 'Current category: %s' => '',
|
'Current category: %s' => 'Aktuelle Kategorie: %s',
|
||||||
// 'no category' => '',
|
'no category' => 'keine Kategorie',
|
||||||
// 'Current assignee: %s' => '',
|
'Current assignee: %s' => 'Aktuelle Zuordnung: %s',
|
||||||
// 'not assigned' => '',
|
'not assigned' => 'nicht zugeordnet',
|
||||||
// 'Author:' => '',
|
'Author:' => 'Autor',
|
||||||
// 'contributors' => '',
|
'contributors' => 'Mitwirkende',
|
||||||
// 'License:' => '',
|
'License:' => 'Lizenz:',
|
||||||
// 'License' => '',
|
'License' => 'Lizenz',
|
||||||
// 'Project Administrator' => '',
|
'Project Administrator' => 'Projektadministrator',
|
||||||
// 'Enter the text below' => '',
|
'Enter the text below' => 'Text unten eingeben',
|
||||||
// 'Gantt chart for %s' => '',
|
'Gantt chart for %s' => 'Gantt Diagramm für %s',
|
||||||
// 'Sort by position' => '',
|
'Sort by position' => 'Nach Position sortieren',
|
||||||
// 'Sort by date' => '',
|
'Sort by date' => 'Nach Datum sortieren',
|
||||||
// 'Add task' => '',
|
'Add task' => 'Aufgabe hinzufügen',
|
||||||
// 'Start date:' => '',
|
'Start date:' => 'Startdatum:',
|
||||||
// 'Due date:' => '',
|
'Due date:' => 'Ablaufdatum:',
|
||||||
// 'There is no start date or due date for this task.' => '',
|
'There is no start date or due date for this task.' => 'Diese Aufgabe hat kein Start oder Ablaufdatum.',
|
||||||
// 'Moving or resizing a task will change the start and due date of the task.' => '',
|
'Moving or resizing a task will change the start and due date of the task.' => 'Aufgabe verschieben/ändern, ändert auch Start- und Ablaufdatum der Aufgabe.',
|
||||||
// 'There is no task in your project.' => '',
|
'There is no task in your project.' => 'Es gibt keine Aufgabe in deinem Projekt',
|
||||||
// 'Gantt chart' => '',
|
'Gantt chart' => 'Gantt Diagramm',
|
||||||
// 'People who are project managers' => '',
|
'People who are project managers' => 'Benutzer die Projektmanager sind',
|
||||||
// 'People who are project members' => '',
|
'People who are project members' => 'Benutzer die Projektmitglieder sind',
|
||||||
// 'NOK - Norwegian Krone' => '',
|
'NOK - Norwegian Krone' => 'NOK - Norwegische Kronen',
|
||||||
// 'Show this column' => '',
|
'Show this column' => 'Spalte anzeigen',
|
||||||
// 'Hide this column' => '',
|
'Hide this column' => 'Spalte verstecken',
|
||||||
// 'open file' => '',
|
'open file' => 'Datei öffnen',
|
||||||
// 'End date' => '',
|
'End date' => 'Endedatum',
|
||||||
// 'Users overview' => '',
|
'Users overview' => 'Benutzerübersicht',
|
||||||
// 'Managers' => '',
|
'Managers' => 'Manager',
|
||||||
// 'Members' => '',
|
'Members' => 'Mitglieder',
|
||||||
// 'Shared project' => '',
|
'Shared project' => 'Geteiltes Projekt',
|
||||||
// 'Project managers' => '',
|
'Project managers' => 'Projektmanager',
|
||||||
// 'Project members' => '',
|
'Project members' => 'Projektmitglieder',
|
||||||
// 'Gantt chart for all projects' => '',
|
'Gantt chart for all projects' => 'Gantt Diagramm für alle Projekte',
|
||||||
// 'Projects list' => '',
|
'Projects list' => 'Projektliste',
|
||||||
// 'Gantt chart for this project' => '',
|
'Gantt chart for this project' => 'Gantt Diagramm für dieses Projekt',
|
||||||
// 'Project board' => '',
|
'Project board' => 'Projekt Pinnwand',
|
||||||
// 'End date:' => '',
|
'End date:' => 'Endedatum:',
|
||||||
// 'There is no start date or end date for this project.' => '',
|
'There is no start date or end date for this project.' => 'Es gibt kein Startdatum oder Endedatum für dieses Projekt',
|
||||||
// 'Projects Gantt chart' => '',
|
'Projects Gantt chart' => 'Projekt Gantt Diagramm',
|
||||||
// 'Start date: %s' => '',
|
'Start date: %s' => 'Beginndatum: %s',
|
||||||
// 'End date: %s' => '',
|
'End date: %s' => 'Enddatum: %s',
|
||||||
// 'Link type' => '',
|
'Link type' => 'Verbindungstyp',
|
||||||
// 'Change task color when using a specific task link' => '',
|
'Change task color when using a specific task link' => 'Aufgabefarbe ändern bei bestimmter Aufgabenverbindung',
|
||||||
// 'Task link creation or modification' => '',
|
'Task link creation or modification' => 'Aufgabenverbindung erstellen oder bearbeiten',
|
||||||
// 'Login with my Gitlab Account' => '',
|
'Login with my Gitlab Account' => 'Mit Gitlab Account einloggen',
|
||||||
// 'Milestone' => '',
|
'Milestone' => 'Meilenstein',
|
||||||
// 'Gitlab Authentication' => '',
|
'Gitlab Authentication' => 'Gitlab-Authentifizierung',
|
||||||
// 'Help on Gitlab authentication' => '',
|
'Help on Gitlab authentication' => 'Hilfe bei Gitlab-Authentifizierung',
|
||||||
// 'Gitlab Id' => '',
|
'Gitlab Id' => 'Gitlab Id',
|
||||||
// 'Gitlab Account' => '',
|
'Gitlab Account' => 'Gitlab Account',
|
||||||
// 'Link my Gitlab Account' => '',
|
'Link my Gitlab Account' => 'Verknüpfe mein Gitlab Account',
|
||||||
// 'Unlink my Gitlab Account' => '',
|
'Unlink my Gitlab Account' => 'Trenne meinen Gitlab Account',
|
||||||
// 'Documentation: %s' => '',
|
'Documentation: %s' => 'Dokumentation: %s',
|
||||||
// 'Switch to the Gantt chart view' => '',
|
'Switch to the Gantt chart view' => 'Zur Gantt-Diagramm Ansicht wechseln',
|
||||||
// 'Reset the search/filter box' => '',
|
'Reset the search/filter box' => 'Suche/Filter-Box zurücksetzen',
|
||||||
// 'Documentation' => '',
|
'Documentation' => 'Dokumentation',
|
||||||
// 'Table of contents' => '',
|
'Table of contents' => 'Inhaltsverzeichnis',
|
||||||
// 'Gantt' => '',
|
'Gantt' => 'Gantt',
|
||||||
// 'Help with project permissions' => '',
|
'Help with project permissions' => 'Hilfe bei Projektberechtigungen',
|
||||||
|
'Author' => 'Autor',
|
||||||
|
'Version' => 'Version',
|
||||||
|
'Plugins' => 'Plugins',
|
||||||
|
'There is no plugin loaded.' => 'Es ist kein Plugin geladen.',
|
||||||
|
'Set maximum column height' => 'Setze maximale Spaltenhöhe',
|
||||||
|
'Remove maximum column height' => 'Entferne maximale Spaltenhöhe',
|
||||||
|
'My notifications' => 'Meine Benachrichtigungen',
|
||||||
|
'Custom filters' => 'benutzerdefinierte Filter',
|
||||||
|
'Your custom filter have been created successfully.' => 'Benutzerdefinierten Filter erfolgreich erstellt.',
|
||||||
|
'Unable to create your custom filter.' => 'Benutzerdefinierter Filter konnte nicht erstellt werden.',
|
||||||
|
'Custom filter removed successfully.' => 'Benutzerdefinierten Filter erfolgreich entfernt.',
|
||||||
|
'Unable to remove this custom filter.' => 'Benutzerdefinierten Filter konnte nicht entfernt werden.',
|
||||||
|
'Edit custom filter' => 'Benutzerdefinierten Filter bearbeiten',
|
||||||
|
'Your custom filter have been updated successfully.' => 'Benutzerdefinierten Filter erfolgreich bearbeitet.',
|
||||||
|
'Unable to update custom filter.' => 'Benutzerdefinierter Filter konnte nicht geändert werden.',
|
||||||
|
'Web' => 'Web',
|
||||||
|
'New attachment on task #%d: %s' => 'Neuer Anhang für Aufgabe #%d: %s',
|
||||||
|
'New comment on task #%d' => 'Neuer Kommentar für Aufgabe #%d',
|
||||||
|
'Comment updated on task #%d' => 'Kommentar geändert für Aufgabe #%d',
|
||||||
|
'New subtask on task #%d' => 'Neue Teilaufgabe für Aufgabe #%d',
|
||||||
|
'Subtask updated on task #%d' => 'Teilaufgabe geändert für Aufgabe #%d',
|
||||||
|
'New task #%d: %s' => 'Neue Aufgabe #%d: %s',
|
||||||
|
'Task updated #%d' => 'Aufgabe bearbeitet #%d',
|
||||||
|
'Task #%d closed' => 'Aufgabe #%d geschlossen',
|
||||||
|
'Task #%d opened' => 'Aufgabe #%d eröffnet',
|
||||||
|
'Column changed for task #%d' => 'Spalte geändert von Aufgabe #%d',
|
||||||
|
'New position for task #%d' => 'Neue Position für Aufgabe #%d',
|
||||||
|
'Swimlane changed for task #%d' => 'Neue Swimlane für Aufgabe #%d',
|
||||||
|
'Assignee changed on task #%d' => 'Neue Zuordnung für Aufgabe #%d ',
|
||||||
|
'%d overdue tasks' => '%d überfällige Aufgaben',
|
||||||
|
'Task #%d is overdue' => 'Aufgabe #%d ist überfällig',
|
||||||
|
'No new notifications.' => 'Keine neuen Benachrichtigungen',
|
||||||
|
'Mark all as read' => 'Alles als gelesen markieren',
|
||||||
|
'Mark as read' => 'Als gelesen markieren',
|
||||||
|
'Total number of tasks in this column across all swimlanes' => 'Anzahl an Aufgaben in dieser Spalte über alle Swimlanes',
|
||||||
|
'Collapse swimlane' => 'Swimlane einklappen',
|
||||||
|
'Expand swimlane' => 'Swimlane ausklappen',
|
||||||
|
'Add a new filter' => 'Neuen Filter hinzufügen',
|
||||||
|
'Share with all project members' => 'Mit allen Projektmitgliedern teilen.',
|
||||||
|
'Shared' => 'Geteilt',
|
||||||
|
'Owner' => 'Eigentümer',
|
||||||
|
'Unread notifications' => 'Ungelesene Benachrichtigungen',
|
||||||
|
'My filters' => 'Meine Filter',
|
||||||
|
'Notification methods:' => 'Benachrichtigungs-Methoden:',
|
||||||
);
|
);
|
||||||
|
|
|
@ -395,8 +395,6 @@ return array(
|
||||||
'Remote' => 'Remota',
|
'Remote' => 'Remota',
|
||||||
'Enabled' => 'Activada',
|
'Enabled' => 'Activada',
|
||||||
'Disabled' => 'Desactivada',
|
'Disabled' => 'Desactivada',
|
||||||
'Google account linked' => 'Vinculada con Cuenta de Google',
|
|
||||||
'Github account linked' => 'Vinculada con Cuenta de Gitgub',
|
|
||||||
'Username:' => 'Nombre de Usuario:',
|
'Username:' => 'Nombre de Usuario:',
|
||||||
'Name:' => 'Nombre:',
|
'Name:' => 'Nombre:',
|
||||||
'Email:' => 'Correo electrónico:',
|
'Email:' => 'Correo electrónico:',
|
||||||
|
@ -667,75 +665,26 @@ return array(
|
||||||
'Horizontal scrolling' => 'Desplazamiento horizontal',
|
'Horizontal scrolling' => 'Desplazamiento horizontal',
|
||||||
'Compact/wide view' => 'Vista compacta/amplia',
|
'Compact/wide view' => 'Vista compacta/amplia',
|
||||||
'No results match:' => 'No hay resultados coincidentes:',
|
'No results match:' => 'No hay resultados coincidentes:',
|
||||||
'Remove hourly rate' => 'Quitar cobro horario',
|
|
||||||
'Do you really want to remove this hourly rate?' => '¿Realmente quire quitar el cobro horario?',
|
|
||||||
'Hourly rates' => 'Cobros horarios',
|
|
||||||
'Hourly rate' => 'Cobro horario',
|
|
||||||
'Currency' => 'Moneda',
|
'Currency' => 'Moneda',
|
||||||
'Effective date' => 'Fecha efectiva',
|
|
||||||
'Add new rate' => 'Añadir nuevo cobro',
|
|
||||||
'Rate removed successfully.' => 'Cobro quitado con éxito.',
|
|
||||||
'Unable to remove this rate.' => 'No pude quitar este cobro.',
|
|
||||||
'Unable to save the hourly rate.' => 'No pude grabar el cobro horario.',
|
|
||||||
'Hourly rate created successfully.' => 'Cobro horario creado con éxito',
|
|
||||||
'Start time' => 'Tiempo de inicio',
|
|
||||||
'End time' => 'Tiempo de fin',
|
|
||||||
'Comment' => 'Comentario',
|
|
||||||
'All day' => 'Todos los días',
|
|
||||||
'Day' => 'Día',
|
|
||||||
'Manage timetable' => 'Gestionar horario',
|
|
||||||
'Overtime timetable' => 'Horario de tiempo extra',
|
|
||||||
'Time off timetable' => 'Horario de tiempo libre',
|
|
||||||
'Timetable' => 'Horario',
|
|
||||||
'Work timetable' => 'Horario de trabajo',
|
|
||||||
'Week timetable' => 'Horario semanal',
|
|
||||||
'Day timetable' => 'Horario diario',
|
|
||||||
'From' => 'De',
|
|
||||||
'To' => 'Para',
|
|
||||||
'Time slot created successfully.' => 'Intervalo de tiempo creado correctamente.',
|
|
||||||
'Unable to save this time slot.' => 'No pude grabar este intervalo de tiempo.',
|
|
||||||
'Time slot removed successfully.' => 'Intervalo de tiempo quitado correctamente.',
|
|
||||||
'Unable to remove this time slot.' => 'No pude quitar este intervalo de tiempo.',
|
|
||||||
'Do you really want to remove this time slot?' => '¿Realmente quiere quitar este intervalo de tiempo?',
|
|
||||||
'Remove time slot' => 'Quitar intervalo de tiempo',
|
|
||||||
'Add new time slot' => 'Añadir nuevo intervalo de tiempo',
|
|
||||||
'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => 'Este horario se usa cuando se marca la casilla "todos los días" para calendario de tiempo libre y horas extras.',
|
|
||||||
'Files' => 'Ficheros',
|
'Files' => 'Ficheros',
|
||||||
'Images' => 'Imágenes',
|
'Images' => 'Imágenes',
|
||||||
'Private project' => 'Proyecto privado',
|
'Private project' => 'Proyecto privado',
|
||||||
'Amount' => 'Cantidad',
|
|
||||||
'AUD - Australian Dollar' => 'AUD - Dólar australiano',
|
'AUD - Australian Dollar' => 'AUD - Dólar australiano',
|
||||||
'Budget' => 'Presupuesto',
|
|
||||||
'Budget line' => 'Línea de presupuesto',
|
|
||||||
'Budget line removed successfully.' => 'Línea de presupuesto quitada con éxito',
|
|
||||||
'Budget lines' => 'Líneas de presupuesto',
|
|
||||||
'CAD - Canadian Dollar' => 'CAD - Dólar canadiense',
|
'CAD - Canadian Dollar' => 'CAD - Dólar canadiense',
|
||||||
'CHF - Swiss Francs' => 'CHF - Francos suizos',
|
'CHF - Swiss Francs' => 'CHF - Francos suizos',
|
||||||
'Cost' => 'Costo',
|
|
||||||
'Cost breakdown' => 'Desglose de costes',
|
|
||||||
'Custom Stylesheet' => 'Hoja de estilo Personalizada',
|
'Custom Stylesheet' => 'Hoja de estilo Personalizada',
|
||||||
'download' => 'descargar',
|
'download' => 'descargar',
|
||||||
'Do you really want to remove this budget line?' => '¿Realmente quiere quitar esta línea de presupuesto?',
|
|
||||||
'EUR - Euro' => 'EUR - Euro',
|
'EUR - Euro' => 'EUR - Euro',
|
||||||
'Expenses' => 'Gastos',
|
|
||||||
'GBP - British Pound' => 'GBP - Libra británica',
|
'GBP - British Pound' => 'GBP - Libra británica',
|
||||||
'INR - Indian Rupee' => 'INR - Rupias indúes',
|
'INR - Indian Rupee' => 'INR - Rupias indúes',
|
||||||
'JPY - Japanese Yen' => 'JPY - Yen japonés',
|
'JPY - Japanese Yen' => 'JPY - Yen japonés',
|
||||||
'New budget line' => 'Nueva línea de presupuesto',
|
|
||||||
'NZD - New Zealand Dollar' => 'NZD - Dóloar neocelandés',
|
'NZD - New Zealand Dollar' => 'NZD - Dóloar neocelandés',
|
||||||
'Remove a budget line' => 'Quitar una línea de presupuesto',
|
|
||||||
'Remove budget line' => 'Quitar línea de presupuesto',
|
|
||||||
'RSD - Serbian dinar' => 'RSD - Dinar serbio',
|
'RSD - Serbian dinar' => 'RSD - Dinar serbio',
|
||||||
'The budget line have been created successfully.' => 'Se ha creado la línea de presupuesto con éxito.',
|
|
||||||
'Unable to create the budget line.' => 'No pude crear la línea de presupuesto.',
|
|
||||||
'Unable to remove this budget line.' => 'No pude quitar esta línea de presupuesto.',
|
|
||||||
'USD - US Dollar' => 'USD - Dólar Estadounidense',
|
'USD - US Dollar' => 'USD - Dólar Estadounidense',
|
||||||
'Remaining' => 'Restante',
|
|
||||||
'Destination column' => 'Columna destino',
|
'Destination column' => 'Columna destino',
|
||||||
'Move the task to another column when assigned to a user' => 'Mover la tarea a otra columna al asignarse al usuario',
|
'Move the task to another column when assigned to a user' => 'Mover la tarea a otra columna al asignarse al usuario',
|
||||||
'Move the task to another column when assignee is cleared' => 'Mover la tarea a otra columna al quitar el concesionario',
|
'Move the task to another column when assignee is cleared' => 'Mover la tarea a otra columna al quitar el concesionario',
|
||||||
'Source column' => 'Columna fuente',
|
'Source column' => 'Columna fuente',
|
||||||
'Show subtask estimates (forecast of future work)' => 'Mostrar estimaciones para la subtarea (pronóstico de trabajo futuro)',
|
|
||||||
'Transitions' => 'Transiciones',
|
'Transitions' => 'Transiciones',
|
||||||
'Executer' => 'Ejecutor',
|
'Executer' => 'Ejecutor',
|
||||||
'Time spent in the column' => 'Tiempo transcurrido en la columna',
|
'Time spent in the column' => 'Tiempo transcurrido en la columna',
|
||||||
|
@ -746,7 +695,6 @@ return array(
|
||||||
'Rate' => 'Cambio',
|
'Rate' => 'Cambio',
|
||||||
'Change reference currency' => 'Cambiar moneda de referencia',
|
'Change reference currency' => 'Cambiar moneda de referencia',
|
||||||
'Add a new currency rate' => 'Añadir nuevo cambio de moneda',
|
'Add a new currency rate' => 'Añadir nuevo cambio de moneda',
|
||||||
'Currency rates are used to calculate project budget.' => 'Se usan los cambios de moneda para calcular el presupuesto del proyecto.',
|
|
||||||
'Reference currency' => 'Moneda de referencia',
|
'Reference currency' => 'Moneda de referencia',
|
||||||
'The currency rate have been added successfully.' => 'Se ha añadido el cambio de moneda con éxito',
|
'The currency rate have been added successfully.' => 'Se ha añadido el cambio de moneda con éxito',
|
||||||
'Unable to add this currency rate.' => 'No pude añadir este cambio de moneda.',
|
'Unable to add this currency rate.' => 'No pude añadir este cambio de moneda.',
|
||||||
|
@ -878,9 +826,6 @@ return array(
|
||||||
'%s moved the task #%d to the first swimlane' => '%s movió la tarea #%d a la primera calle',
|
'%s moved the task #%d to the first swimlane' => '%s movió la tarea #%d a la primera calle',
|
||||||
'%s moved the task #%d to the swimlane "%s"' => '%s movió la tarea #%d a la calle "%s"',
|
'%s moved the task #%d to the swimlane "%s"' => '%s movió la tarea #%d a la calle "%s"',
|
||||||
'Swimlane' => 'Calle',
|
'Swimlane' => 'Calle',
|
||||||
'Budget overview' => 'Resumen del Presupuesto',
|
|
||||||
'Type' => 'Tipo',
|
|
||||||
'There is not enough data to show something.' => 'No hay datos suficientes como para mostrar algo.',
|
|
||||||
'Gravatar' => 'Gravatar',
|
'Gravatar' => 'Gravatar',
|
||||||
'Hipchat' => 'Hipchat',
|
'Hipchat' => 'Hipchat',
|
||||||
'Slack' => 'Desatendida',
|
'Slack' => 'Desatendida',
|
||||||
|
@ -1040,31 +985,75 @@ return array(
|
||||||
'Shared project' => 'Proyecto compartido',
|
'Shared project' => 'Proyecto compartido',
|
||||||
'Project managers' => 'Administradores de proyecto',
|
'Project managers' => 'Administradores de proyecto',
|
||||||
'Project members' => 'Miembros de proyecto',
|
'Project members' => 'Miembros de proyecto',
|
||||||
// 'Gantt chart for all projects' => '',
|
'Gantt chart for all projects' => 'Diagrama de Gantt para todos los proyectos',
|
||||||
// 'Projects list' => '',
|
'Projects list' => 'Lista de proyectos',
|
||||||
// 'Gantt chart for this project' => '',
|
'Gantt chart for this project' => 'Diagrama de Gantt para este proyecto',
|
||||||
// 'Project board' => '',
|
'Project board' => 'Tablero del proyecto',
|
||||||
// 'End date:' => '',
|
'End date:' => 'Fecha final',
|
||||||
// 'There is no start date or end date for this project.' => '',
|
'There is no start date or end date for this project.' => 'No existe fecha de inicio o de fin para este proyecto.',
|
||||||
// 'Projects Gantt chart' => '',
|
'Projects Gantt chart' => 'Diagramas de Gantt de los proyectos',
|
||||||
// 'Start date: %s' => '',
|
'Start date: %s' => 'Fecha inicial: %s',
|
||||||
// 'End date: %s' => '',
|
'End date: %s' => 'Fecha final: %s',
|
||||||
// 'Link type' => '',
|
'Link type' => 'Tipo de enlace',
|
||||||
// 'Change task color when using a specific task link' => '',
|
'Change task color when using a specific task link' => 'Cambiar colo de la tarea al usar un enlace específico a tarea',
|
||||||
// 'Task link creation or modification' => '',
|
'Task link creation or modification' => 'Creación o modificación de enlace a tarea',
|
||||||
// 'Login with my Gitlab Account' => '',
|
'Login with my Gitlab Account' => 'Ingresar usando mi Cuenta en Gitlab',
|
||||||
// 'Milestone' => '',
|
'Milestone' => 'Hito',
|
||||||
// 'Gitlab Authentication' => '',
|
'Gitlab Authentication' => 'Autenticación Gitlab',
|
||||||
// 'Help on Gitlab authentication' => '',
|
'Help on Gitlab authentication' => 'Ayuda con autenticación Gitlab',
|
||||||
// 'Gitlab Id' => '',
|
'Gitlab Id' => 'Id de Gitlab',
|
||||||
// 'Gitlab Account' => '',
|
'Gitlab Account' => 'Cuenta de Gitlab',
|
||||||
// 'Link my Gitlab Account' => '',
|
'Link my Gitlab Account' => 'Enlazar con mi Cuenta en Gitlab',
|
||||||
// 'Unlink my Gitlab Account' => '',
|
'Unlink my Gitlab Account' => 'Desenlazar con mi Cuenta en Gitlab',
|
||||||
// 'Documentation: %s' => '',
|
'Documentation: %s' => 'Documentación: %s',
|
||||||
// 'Switch to the Gantt chart view' => '',
|
'Switch to the Gantt chart view' => 'Conmutar a vista de diagrama de Gantt',
|
||||||
// 'Reset the search/filter box' => '',
|
'Reset the search/filter box' => 'Limpiar la caja del filtro de búsqueda',
|
||||||
// 'Documentation' => '',
|
'Documentation' => 'Documentación',
|
||||||
// 'Table of contents' => '',
|
'Table of contents' => 'Tabla de contenido',
|
||||||
// 'Gantt' => '',
|
'Gantt' => 'Gantt',
|
||||||
// 'Help with project permissions' => '',
|
'Help with project permissions' => 'Ayuda con permisos del proyecto',
|
||||||
|
// 'Author' => '',
|
||||||
|
// 'Version' => '',
|
||||||
|
// 'Plugins' => '',
|
||||||
|
// 'There is no plugin loaded.' => '',
|
||||||
|
// 'Set maximum column height' => '',
|
||||||
|
// 'Remove maximum column height' => '',
|
||||||
|
// 'My notifications' => '',
|
||||||
|
// 'Custom filters' => '',
|
||||||
|
// 'Your custom filter have been created successfully.' => '',
|
||||||
|
// 'Unable to create your custom filter.' => '',
|
||||||
|
// 'Custom filter removed successfully.' => '',
|
||||||
|
// 'Unable to remove this custom filter.' => '',
|
||||||
|
// 'Edit custom filter' => '',
|
||||||
|
// 'Your custom filter have been updated successfully.' => '',
|
||||||
|
// 'Unable to update custom filter.' => '',
|
||||||
|
// 'Web' => '',
|
||||||
|
// 'New attachment on task #%d: %s' => '',
|
||||||
|
// 'New comment on task #%d' => '',
|
||||||
|
// 'Comment updated on task #%d' => '',
|
||||||
|
// 'New subtask on task #%d' => '',
|
||||||
|
// 'Subtask updated on task #%d' => '',
|
||||||
|
// 'New task #%d: %s' => '',
|
||||||
|
// 'Task updated #%d' => '',
|
||||||
|
// 'Task #%d closed' => '',
|
||||||
|
// 'Task #%d opened' => '',
|
||||||
|
// 'Column changed for task #%d' => '',
|
||||||
|
// 'New position for task #%d' => '',
|
||||||
|
// 'Swimlane changed for task #%d' => '',
|
||||||
|
// 'Assignee changed on task #%d' => '',
|
||||||
|
// '%d overdue tasks' => '',
|
||||||
|
// 'Task #%d is overdue' => '',
|
||||||
|
// 'No new notifications.' => '',
|
||||||
|
// 'Mark all as read' => '',
|
||||||
|
// 'Mark as read' => '',
|
||||||
|
// 'Total number of tasks in this column across all swimlanes' => '',
|
||||||
|
// 'Collapse swimlane' => '',
|
||||||
|
// 'Expand swimlane' => '',
|
||||||
|
// 'Add a new filter' => '',
|
||||||
|
// 'Share with all project members' => '',
|
||||||
|
// 'Shared' => '',
|
||||||
|
// 'Owner' => '',
|
||||||
|
// 'Unread notifications' => '',
|
||||||
|
// 'My filters' => '',
|
||||||
|
// 'Notification methods:' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -395,8 +395,6 @@ return array(
|
||||||
'Remote' => 'Etä',
|
'Remote' => 'Etä',
|
||||||
'Enabled' => 'Käytössä',
|
'Enabled' => 'Käytössä',
|
||||||
'Disabled' => 'Pois käytöstä',
|
'Disabled' => 'Pois käytöstä',
|
||||||
'Google account linked' => 'Google-tili liitetty',
|
|
||||||
'Github account linked' => 'Github-tili liitetty',
|
|
||||||
'Username:' => 'Käyttäjänimi:',
|
'Username:' => 'Käyttäjänimi:',
|
||||||
'Name:' => 'Nimi:',
|
'Name:' => 'Nimi:',
|
||||||
'Email:' => 'Sähköpostiosoite:',
|
'Email:' => 'Sähköpostiosoite:',
|
||||||
|
@ -667,75 +665,26 @@ return array(
|
||||||
// 'Horizontal scrolling' => '',
|
// 'Horizontal scrolling' => '',
|
||||||
// 'Compact/wide view' => '',
|
// 'Compact/wide view' => '',
|
||||||
// 'No results match:' => '',
|
// 'No results match:' => '',
|
||||||
// 'Remove hourly rate' => '',
|
|
||||||
// 'Do you really want to remove this hourly rate?' => '',
|
|
||||||
// 'Hourly rates' => '',
|
|
||||||
// 'Hourly rate' => '',
|
|
||||||
// 'Currency' => '',
|
// 'Currency' => '',
|
||||||
// 'Effective date' => '',
|
|
||||||
// 'Add new rate' => '',
|
|
||||||
// 'Rate removed successfully.' => '',
|
|
||||||
// 'Unable to remove this rate.' => '',
|
|
||||||
// 'Unable to save the hourly rate.' => '',
|
|
||||||
// 'Hourly rate created successfully.' => '',
|
|
||||||
// 'Start time' => '',
|
|
||||||
// 'End time' => '',
|
|
||||||
// 'Comment' => '',
|
|
||||||
// 'All day' => '',
|
|
||||||
// 'Day' => '',
|
|
||||||
// 'Manage timetable' => '',
|
|
||||||
// 'Overtime timetable' => '',
|
|
||||||
// 'Time off timetable' => '',
|
|
||||||
// 'Timetable' => '',
|
|
||||||
// 'Work timetable' => '',
|
|
||||||
// 'Week timetable' => '',
|
|
||||||
// 'Day timetable' => '',
|
|
||||||
// 'From' => '',
|
|
||||||
// 'To' => '',
|
|
||||||
// 'Time slot created successfully.' => '',
|
|
||||||
// 'Unable to save this time slot.' => '',
|
|
||||||
// 'Time slot removed successfully.' => '',
|
|
||||||
// 'Unable to remove this time slot.' => '',
|
|
||||||
// 'Do you really want to remove this time slot?' => '',
|
|
||||||
// 'Remove time slot' => '',
|
|
||||||
// 'Add new time slot' => '',
|
|
||||||
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
|
|
||||||
// 'Files' => '',
|
// 'Files' => '',
|
||||||
// 'Images' => '',
|
// 'Images' => '',
|
||||||
// 'Private project' => '',
|
// 'Private project' => '',
|
||||||
// 'Amount' => '',
|
|
||||||
// 'AUD - Australian Dollar' => '',
|
// 'AUD - Australian Dollar' => '',
|
||||||
// 'Budget' => '',
|
|
||||||
// 'Budget line' => '',
|
|
||||||
// 'Budget line removed successfully.' => '',
|
|
||||||
// 'Budget lines' => '',
|
|
||||||
// 'CAD - Canadian Dollar' => '',
|
// 'CAD - Canadian Dollar' => '',
|
||||||
// 'CHF - Swiss Francs' => '',
|
// 'CHF - Swiss Francs' => '',
|
||||||
// 'Cost' => '',
|
|
||||||
// 'Cost breakdown' => '',
|
|
||||||
// 'Custom Stylesheet' => '',
|
// 'Custom Stylesheet' => '',
|
||||||
// 'download' => '',
|
// 'download' => '',
|
||||||
// 'Do you really want to remove this budget line?' => '',
|
|
||||||
// 'EUR - Euro' => '',
|
// 'EUR - Euro' => '',
|
||||||
// 'Expenses' => '',
|
|
||||||
// 'GBP - British Pound' => '',
|
// 'GBP - British Pound' => '',
|
||||||
// 'INR - Indian Rupee' => '',
|
// 'INR - Indian Rupee' => '',
|
||||||
// 'JPY - Japanese Yen' => '',
|
// 'JPY - Japanese Yen' => '',
|
||||||
// 'New budget line' => '',
|
|
||||||
// 'NZD - New Zealand Dollar' => '',
|
// 'NZD - New Zealand Dollar' => '',
|
||||||
// 'Remove a budget line' => '',
|
|
||||||
// 'Remove budget line' => '',
|
|
||||||
// 'RSD - Serbian dinar' => '',
|
// 'RSD - Serbian dinar' => '',
|
||||||
// 'The budget line have been created successfully.' => '',
|
|
||||||
// 'Unable to create the budget line.' => '',
|
|
||||||
// 'Unable to remove this budget line.' => '',
|
|
||||||
// 'USD - US Dollar' => '',
|
// 'USD - US Dollar' => '',
|
||||||
// 'Remaining' => '',
|
|
||||||
// 'Destination column' => '',
|
// 'Destination column' => '',
|
||||||
// 'Move the task to another column when assigned to a user' => '',
|
// 'Move the task to another column when assigned to a user' => '',
|
||||||
// 'Move the task to another column when assignee is cleared' => '',
|
// 'Move the task to another column when assignee is cleared' => '',
|
||||||
// 'Source column' => '',
|
// 'Source column' => '',
|
||||||
// 'Show subtask estimates (forecast of future work)' => '',
|
|
||||||
// 'Transitions' => '',
|
// 'Transitions' => '',
|
||||||
// 'Executer' => '',
|
// 'Executer' => '',
|
||||||
// 'Time spent in the column' => '',
|
// 'Time spent in the column' => '',
|
||||||
|
@ -746,7 +695,6 @@ return array(
|
||||||
// 'Rate' => '',
|
// 'Rate' => '',
|
||||||
// 'Change reference currency' => '',
|
// 'Change reference currency' => '',
|
||||||
// 'Add a new currency rate' => '',
|
// 'Add a new currency rate' => '',
|
||||||
// 'Currency rates are used to calculate project budget.' => '',
|
|
||||||
// 'Reference currency' => '',
|
// 'Reference currency' => '',
|
||||||
// 'The currency rate have been added successfully.' => '',
|
// 'The currency rate have been added successfully.' => '',
|
||||||
// 'Unable to add this currency rate.' => '',
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
@ -878,9 +826,6 @@ return array(
|
||||||
// '%s moved the task #%d to the first swimlane' => '',
|
// '%s moved the task #%d to the first swimlane' => '',
|
||||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||||
// 'Swimlane' => '',
|
// 'Swimlane' => '',
|
||||||
// 'Budget overview' => '',
|
|
||||||
// 'Type' => '',
|
|
||||||
// 'There is not enough data to show something.' => '',
|
|
||||||
// 'Gravatar' => '',
|
// 'Gravatar' => '',
|
||||||
// 'Hipchat' => '',
|
// 'Hipchat' => '',
|
||||||
// 'Slack' => '',
|
// 'Slack' => '',
|
||||||
|
@ -1067,4 +1012,48 @@ return array(
|
||||||
// 'Table of contents' => '',
|
// 'Table of contents' => '',
|
||||||
// 'Gantt' => '',
|
// 'Gantt' => '',
|
||||||
// 'Help with project permissions' => '',
|
// 'Help with project permissions' => '',
|
||||||
|
// 'Author' => '',
|
||||||
|
// 'Version' => '',
|
||||||
|
// 'Plugins' => '',
|
||||||
|
// 'There is no plugin loaded.' => '',
|
||||||
|
// 'Set maximum column height' => '',
|
||||||
|
// 'Remove maximum column height' => '',
|
||||||
|
// 'My notifications' => '',
|
||||||
|
// 'Custom filters' => '',
|
||||||
|
// 'Your custom filter have been created successfully.' => '',
|
||||||
|
// 'Unable to create your custom filter.' => '',
|
||||||
|
// 'Custom filter removed successfully.' => '',
|
||||||
|
// 'Unable to remove this custom filter.' => '',
|
||||||
|
// 'Edit custom filter' => '',
|
||||||
|
// 'Your custom filter have been updated successfully.' => '',
|
||||||
|
// 'Unable to update custom filter.' => '',
|
||||||
|
// 'Web' => '',
|
||||||
|
// 'New attachment on task #%d: %s' => '',
|
||||||
|
// 'New comment on task #%d' => '',
|
||||||
|
// 'Comment updated on task #%d' => '',
|
||||||
|
// 'New subtask on task #%d' => '',
|
||||||
|
// 'Subtask updated on task #%d' => '',
|
||||||
|
// 'New task #%d: %s' => '',
|
||||||
|
// 'Task updated #%d' => '',
|
||||||
|
// 'Task #%d closed' => '',
|
||||||
|
// 'Task #%d opened' => '',
|
||||||
|
// 'Column changed for task #%d' => '',
|
||||||
|
// 'New position for task #%d' => '',
|
||||||
|
// 'Swimlane changed for task #%d' => '',
|
||||||
|
// 'Assignee changed on task #%d' => '',
|
||||||
|
// '%d overdue tasks' => '',
|
||||||
|
// 'Task #%d is overdue' => '',
|
||||||
|
// 'No new notifications.' => '',
|
||||||
|
// 'Mark all as read' => '',
|
||||||
|
// 'Mark as read' => '',
|
||||||
|
// 'Total number of tasks in this column across all swimlanes' => '',
|
||||||
|
// 'Collapse swimlane' => '',
|
||||||
|
// 'Expand swimlane' => '',
|
||||||
|
// 'Add a new filter' => '',
|
||||||
|
// 'Share with all project members' => '',
|
||||||
|
// 'Shared' => '',
|
||||||
|
// 'Owner' => '',
|
||||||
|
// 'Unread notifications' => '',
|
||||||
|
// 'My filters' => '',
|
||||||
|
// 'Notification methods:' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -75,19 +75,19 @@ return array(
|
||||||
'Change columns' => 'Changer les colonnes',
|
'Change columns' => 'Changer les colonnes',
|
||||||
'Add a new column' => 'Ajouter une nouvelle colonne',
|
'Add a new column' => 'Ajouter une nouvelle colonne',
|
||||||
'Title' => 'Titre',
|
'Title' => 'Titre',
|
||||||
'Nobody assigned' => 'Personne assigné',
|
'Nobody assigned' => 'Personne assignée',
|
||||||
'Assigned to %s' => 'Assigné à %s',
|
'Assigned to %s' => 'Assigné à %s',
|
||||||
'Remove a column' => 'Supprimer une colonne',
|
'Remove a column' => 'Supprimer une colonne',
|
||||||
'Remove a column from a board' => 'Supprimer une colonne d\'un tableau',
|
'Remove a column from a board' => 'Supprimer une colonne d\'un tableau',
|
||||||
'Unable to remove this column.' => 'Impossible de supprimer cette colonne.',
|
'Unable to remove this column.' => 'Impossible de supprimer cette colonne.',
|
||||||
'Do you really want to remove this column: "%s"?' => 'Voulez vraiment supprimer cette colonne : « %s » ?',
|
'Do you really want to remove this column: "%s"?' => 'Voulez vraiment supprimer cette colonne : « %s » ?',
|
||||||
'This action will REMOVE ALL TASKS associated to this column!' => 'Cette action va supprimer toutes les tâches associées à cette colonne !',
|
'This action will REMOVE ALL TASKS associated to this column!' => 'Cette action va supprimer toutes les tâches associées à cette colonne !',
|
||||||
'Settings' => 'Préférences',
|
'Settings' => 'Préférences',
|
||||||
'Application settings' => 'Paramètres de l\'application',
|
'Application settings' => 'Paramètres de l\'application',
|
||||||
'Language' => 'Langue',
|
'Language' => 'Langue',
|
||||||
'Webhook token:' => 'Jeton de securité pour les webhooks :',
|
'Webhook token:' => 'Jeton de securité pour les webhooks :',
|
||||||
'API token:' => 'Jeton de securité pour l\'API :',
|
'API token:' => 'Jeton de securité pour l\'API :',
|
||||||
'Database size:' => 'Taille de la base de données :',
|
'Database size:' => 'Taille de la base de données :',
|
||||||
'Download the database' => 'Télécharger la base de données',
|
'Download the database' => 'Télécharger la base de données',
|
||||||
'Optimize the database' => 'Optimiser la base de données',
|
'Optimize the database' => 'Optimiser la base de données',
|
||||||
'(VACUUM command)' => '(Commande VACUUM)',
|
'(VACUUM command)' => '(Commande VACUUM)',
|
||||||
|
@ -96,15 +96,15 @@ return array(
|
||||||
'Edit a task' => 'Modifier une tâche',
|
'Edit a task' => 'Modifier une tâche',
|
||||||
'Column' => 'Colonne',
|
'Column' => 'Colonne',
|
||||||
'Color' => 'Couleur',
|
'Color' => 'Couleur',
|
||||||
'Assignee' => 'Personne assignée',
|
'Assignee' => 'Personne assigné',
|
||||||
'Create another task' => 'Créer une autre tâche',
|
'Create another task' => 'Créer une autre tâche',
|
||||||
'New task' => 'Nouvelle tâche',
|
'New task' => 'Nouvelle tâche',
|
||||||
'Open a task' => 'Ouvrir une tâche',
|
'Open a task' => 'Ouvrir une tâche',
|
||||||
'Do you really want to open this task: "%s"?' => 'Voulez-vous vraiment ouvrir cette tâche : « %s » ?',
|
'Do you really want to open this task: "%s"?' => 'Voulez-vous vraiment ouvrir cette tâche : « %s » ?',
|
||||||
'Back to the board' => 'Retour au tableau',
|
'Back to the board' => 'Retour au tableau',
|
||||||
'Created on %B %e, %Y at %k:%M %p' => 'Créé le %d/%m/%Y à %H:%M',
|
'Created on %B %e, %Y at %k:%M %p' => 'Créé le %d/%m/%Y à %H:%M',
|
||||||
'There is nobody assigned' => 'Il n\'y a personne d\'assigné à cette tâche',
|
'There is nobody assigned' => 'Il n\'y a personne d\'assigné à cette tâche',
|
||||||
'Column on the board:' => 'Colonne sur le tableau : ',
|
'Column on the board:' => 'Colonne sur le tableau : ',
|
||||||
'Status is open' => 'État ouvert',
|
'Status is open' => 'État ouvert',
|
||||||
'Status is closed' => 'État fermé',
|
'Status is closed' => 'État fermé',
|
||||||
'Close this task' => 'Fermer cette tâche',
|
'Close this task' => 'Fermer cette tâche',
|
||||||
|
@ -142,7 +142,7 @@ return array(
|
||||||
'Unable to open this task.' => 'Impossible d\'ouvrir cette tâche.',
|
'Unable to open this task.' => 'Impossible d\'ouvrir cette tâche.',
|
||||||
'Task opened successfully.' => 'Tâche ouverte avec succès.',
|
'Task opened successfully.' => 'Tâche ouverte avec succès.',
|
||||||
'Unable to close this task.' => 'Impossible de fermer cette tâche.',
|
'Unable to close this task.' => 'Impossible de fermer cette tâche.',
|
||||||
'Task closed successfully.' => 'Tâche fermé avec succès.',
|
'Task closed successfully.' => 'Tâche fermée avec succès.',
|
||||||
'Unable to update your task.' => 'Impossible de modifier cette tâche.',
|
'Unable to update your task.' => 'Impossible de modifier cette tâche.',
|
||||||
'Task updated successfully.' => 'Tâche mise à jour avec succès.',
|
'Task updated successfully.' => 'Tâche mise à jour avec succès.',
|
||||||
'Unable to create your task.' => 'Impossible de créer cette tâche.',
|
'Unable to create your task.' => 'Impossible de créer cette tâche.',
|
||||||
|
@ -167,11 +167,11 @@ return array(
|
||||||
'%d closed tasks' => '%d tâches terminées',
|
'%d closed tasks' => '%d tâches terminées',
|
||||||
'No task for this project' => 'Aucune tâche pour ce projet',
|
'No task for this project' => 'Aucune tâche pour ce projet',
|
||||||
'Public link' => 'Lien public',
|
'Public link' => 'Lien public',
|
||||||
'There is no column in your project!' => 'Il n\'y a aucune colonne dans votre projet !',
|
'There is no column in your project!' => 'Il n\'y a aucune colonne dans votre projet !',
|
||||||
'Change assignee' => 'Changer la personne assignée',
|
'Change assignee' => 'Changer la personne assignée',
|
||||||
'Change assignee for the task "%s"' => 'Changer la personne assignée pour la tâche « %s »',
|
'Change assignee for the task "%s"' => 'Changer la personne assignée pour la tâche « %s »',
|
||||||
'Timezone' => 'Fuseau horaire',
|
'Timezone' => 'Fuseau horaire',
|
||||||
'Sorry, I didn\'t find this information in my database!' => 'Désolé, je n\'ai pas trouvé cette information dans ma base de données !',
|
'Sorry, I didn\'t find this information in my database!' => 'Désolé, je n\'ai pas trouvé cette information dans ma base de données !',
|
||||||
'Page not found' => 'Page introuvable',
|
'Page not found' => 'Page introuvable',
|
||||||
'Complexity' => 'Complexité',
|
'Complexity' => 'Complexité',
|
||||||
'Task limit' => 'Tâches Max.',
|
'Task limit' => 'Tâches Max.',
|
||||||
|
@ -197,7 +197,7 @@ return array(
|
||||||
'%B %e, %Y' => '%d %B %Y',
|
'%B %e, %Y' => '%d %B %Y',
|
||||||
'%b %e, %Y' => '%d/%m/%Y',
|
'%b %e, %Y' => '%d/%m/%Y',
|
||||||
'Automatic actions' => 'Actions automatisées',
|
'Automatic actions' => 'Actions automatisées',
|
||||||
'Your automatic action have been created successfully.' => 'Votre action automatisée a été ajouté avec succès.',
|
'Your automatic action have been created successfully.' => 'Votre action automatisée a été ajoutée avec succès.',
|
||||||
'Unable to create your automatic action.' => 'Impossible de créer votre action automatisée.',
|
'Unable to create your automatic action.' => 'Impossible de créer votre action automatisée.',
|
||||||
'Remove an action' => 'Supprimer une action',
|
'Remove an action' => 'Supprimer une action',
|
||||||
'Unable to remove this action.' => 'Impossible de supprimer cette action',
|
'Unable to remove this action.' => 'Impossible de supprimer cette action',
|
||||||
|
@ -210,7 +210,7 @@ return array(
|
||||||
'Action parameters' => 'Paramètres de l\'action',
|
'Action parameters' => 'Paramètres de l\'action',
|
||||||
'Action' => 'Action',
|
'Action' => 'Action',
|
||||||
'Event' => 'Événement',
|
'Event' => 'Événement',
|
||||||
'When the selected event occurs execute the corresponding action.' => 'Lorsque l\'événement sélectionné se déclenche, executer l\'action correspondante.',
|
'When the selected event occurs execute the corresponding action.' => 'Lorsque l\'événement sélectionné se déclenche, exécuter l\'action correspondante.',
|
||||||
'Next step' => 'Étape suivante',
|
'Next step' => 'Étape suivante',
|
||||||
'Define action parameters' => 'Définition des paramètres de l\'action',
|
'Define action parameters' => 'Définition des paramètres de l\'action',
|
||||||
'Save this action' => 'Sauvegarder cette action',
|
'Save this action' => 'Sauvegarder cette action',
|
||||||
|
@ -237,10 +237,10 @@ return array(
|
||||||
'Comment removed successfully.' => 'Commentaire supprimé avec succès.',
|
'Comment removed successfully.' => 'Commentaire supprimé avec succès.',
|
||||||
'Unable to remove this comment.' => 'Impossible de supprimer ce commentaire.',
|
'Unable to remove this comment.' => 'Impossible de supprimer ce commentaire.',
|
||||||
'Do you really want to remove this comment?' => 'Voulez-vous vraiment supprimer ce commentaire ?',
|
'Do you really want to remove this comment?' => 'Voulez-vous vraiment supprimer ce commentaire ?',
|
||||||
'Only administrators or the creator of the comment can access to this page.' => 'Uniquement les administrateurs ou le créateur du commentaire peuvent accéder à cette page.',
|
'Only administrators or the creator of the comment can access to this page.' => 'Seuls les administrateurs ou le créateur du commentaire peuvent accéder à cette page.',
|
||||||
'Current password for the user "%s"' => 'Mot de passe actuel pour l\'utilisateur « %s »',
|
'Current password for the user "%s"' => 'Mot de passe actuel pour l\'utilisateur « %s »',
|
||||||
'The current password is required' => 'Le mot de passe actuel est obligatoire',
|
'The current password is required' => 'Le mot de passe actuel est obligatoire',
|
||||||
'Wrong password' => 'Mauvais mot de passe',
|
'Wrong password' => 'Mot de passe invalide',
|
||||||
'Unknown' => 'Inconnu',
|
'Unknown' => 'Inconnu',
|
||||||
'Last logins' => 'Dernières connexions',
|
'Last logins' => 'Dernières connexions',
|
||||||
'Login date' => 'Date de connexion',
|
'Login date' => 'Date de connexion',
|
||||||
|
@ -263,10 +263,10 @@ return array(
|
||||||
'%d comments' => '%d commentaires',
|
'%d comments' => '%d commentaires',
|
||||||
'%d comment' => '%d commentaire',
|
'%d comment' => '%d commentaire',
|
||||||
'Email address invalid' => 'Adresse email invalide',
|
'Email address invalid' => 'Adresse email invalide',
|
||||||
'Your external account is not linked anymore to your profile.' => 'Votre compte externe n\'est plus relié à votre profile.',
|
'Your external account is not linked anymore to your profile.' => 'Votre compte externe n\'est plus relié à votre profil.',
|
||||||
'Unable to unlink your external account.' => 'Impossible de supprimer votre compte externe.',
|
'Unable to unlink your external account.' => 'Impossible de supprimer votre compte externe.',
|
||||||
'External authentication failed' => 'Authentification externe échouée',
|
'External authentication failed' => 'L’authentification externe a échoué',
|
||||||
'Your external account is linked to your profile successfully.' => 'Votre compte externe est désormais lié à votre profile.',
|
'Your external account is linked to your profile successfully.' => 'Votre compte externe est désormais lié à votre profil.',
|
||||||
'Email' => 'Email',
|
'Email' => 'Email',
|
||||||
'Link my Google Account' => 'Lier mon compte Google',
|
'Link my Google Account' => 'Lier mon compte Google',
|
||||||
'Unlink my Google Account' => 'Ne plus utiliser mon compte Google',
|
'Unlink my Google Account' => 'Ne plus utiliser mon compte Google',
|
||||||
|
@ -283,7 +283,7 @@ return array(
|
||||||
'Category:' => 'Catégorie :',
|
'Category:' => 'Catégorie :',
|
||||||
'Categories' => 'Catégories',
|
'Categories' => 'Catégories',
|
||||||
'Category not found.' => 'Catégorie introuvable',
|
'Category not found.' => 'Catégorie introuvable',
|
||||||
'Your category have been created successfully.' => 'Votre catégorie a été créé avec succès.',
|
'Your category have been created successfully.' => 'Votre catégorie a été créée avec succès.',
|
||||||
'Unable to create your category.' => 'Impossible de créer votre catégorie.',
|
'Unable to create your category.' => 'Impossible de créer votre catégorie.',
|
||||||
'Your category have been updated successfully.' => 'Votre catégorie a été mise à jour avec succès.',
|
'Your category have been updated successfully.' => 'Votre catégorie a été mise à jour avec succès.',
|
||||||
'Unable to update your category.' => 'Impossible de mettre à jour votre catégorie.',
|
'Unable to update your category.' => 'Impossible de mettre à jour votre catégorie.',
|
||||||
|
@ -311,13 +311,13 @@ return array(
|
||||||
'Summary' => 'Résumé',
|
'Summary' => 'Résumé',
|
||||||
'Time tracking' => 'Suivi du temps',
|
'Time tracking' => 'Suivi du temps',
|
||||||
'Estimate:' => 'Estimation :',
|
'Estimate:' => 'Estimation :',
|
||||||
'Spent:' => 'Passé :',
|
'Spent:' => 'Passé :',
|
||||||
'Do you really want to remove this sub-task?' => 'Voulez-vous vraiment supprimer cette sous-tâche ?',
|
'Do you really want to remove this sub-task?' => 'Voulez-vous vraiment supprimer cette sous-tâche ?',
|
||||||
'Remaining:' => 'Restant :',
|
'Remaining:' => 'Restant :',
|
||||||
'hours' => 'heures',
|
'hours' => 'heures',
|
||||||
'spent' => 'passé',
|
'spent' => 'passé',
|
||||||
'estimated' => 'estimé',
|
'estimated' => 'estimé',
|
||||||
'Sub-Tasks' => 'Sous-Tâches',
|
'Sub-Tasks' => 'Sous-tâches',
|
||||||
'Add a sub-task' => 'Ajouter une sous-tâche',
|
'Add a sub-task' => 'Ajouter une sous-tâche',
|
||||||
'Original estimate' => 'Estimation originale',
|
'Original estimate' => 'Estimation originale',
|
||||||
'Create another sub-task' => 'Créer une autre sous-tâche',
|
'Create another sub-task' => 'Créer une autre sous-tâche',
|
||||||
|
@ -332,8 +332,8 @@ return array(
|
||||||
'Sub-task updated successfully.' => 'Sous-tâche mise à jour avec succès.',
|
'Sub-task updated successfully.' => 'Sous-tâche mise à jour avec succès.',
|
||||||
'Unable to update your sub-task.' => 'Impossible de mettre à jour votre sous-tâche.',
|
'Unable to update your sub-task.' => 'Impossible de mettre à jour votre sous-tâche.',
|
||||||
'Unable to create your sub-task.' => 'Impossible de créer votre sous-tâche.',
|
'Unable to create your sub-task.' => 'Impossible de créer votre sous-tâche.',
|
||||||
'Sub-task added successfully.' => 'Sous-tâche ajouté avec succès.',
|
'Sub-task added successfully.' => 'Sous-tâche ajoutée avec succès.',
|
||||||
'Maximum size: ' => 'Taille maximum : ',
|
'Maximum size: ' => 'Taille maximum : ',
|
||||||
'Unable to upload the file.' => 'Impossible de transférer le fichier.',
|
'Unable to upload the file.' => 'Impossible de transférer le fichier.',
|
||||||
'Display another project' => 'Afficher un autre projet',
|
'Display another project' => 'Afficher un autre projet',
|
||||||
'Login with my Github Account' => 'Se connecter avec mon compte Github',
|
'Login with my Github Account' => 'Se connecter avec mon compte Github',
|
||||||
|
@ -397,8 +397,6 @@ return array(
|
||||||
'Remote' => 'Distant',
|
'Remote' => 'Distant',
|
||||||
'Enabled' => 'Activé',
|
'Enabled' => 'Activé',
|
||||||
'Disabled' => 'Désactivé',
|
'Disabled' => 'Désactivé',
|
||||||
'Google account linked' => 'Compte Google attaché',
|
|
||||||
'Github account linked' => 'Compte Github attaché',
|
|
||||||
'Username:' => 'Nom d\'utilisateur :',
|
'Username:' => 'Nom d\'utilisateur :',
|
||||||
'Name:' => 'Nom :',
|
'Name:' => 'Nom :',
|
||||||
'Email:' => 'Email :',
|
'Email:' => 'Email :',
|
||||||
|
@ -447,10 +445,10 @@ return array(
|
||||||
'%s moved the task #%d to the position %d in the column "%s"' => '%s a déplacé la tâche n°%d à la position n°%d dans la colonne « %s »',
|
'%s moved the task #%d to the position %d in the column "%s"' => '%s a déplacé la tâche n°%d à la position n°%d dans la colonne « %s »',
|
||||||
'Activity' => 'Activité',
|
'Activity' => 'Activité',
|
||||||
'Default values are "%s"' => 'Les valeurs par défaut sont « %s »',
|
'Default values are "%s"' => 'Les valeurs par défaut sont « %s »',
|
||||||
'Default columns for new projects (Comma-separated)' => 'Colonnes par défaut pour les nouveaux projets (séparé par des virgules)',
|
'Default columns for new projects (Comma-separated)' => 'Colonnes par défaut pour les nouveaux projets (séparation par des virgules)',
|
||||||
'Task assignee change' => 'Modification de la personne assignée sur une tâche',
|
'Task assignee change' => 'Modification de la personne assignée à une tâche',
|
||||||
'%s change the assignee of the task #%d to %s' => '%s a changé la personne assignée sur la tâche n˚%d pour %s',
|
'%s change the assignee of the task #%d to %s' => '%s a changé la personne assignée à la tâche n˚%d pour %s',
|
||||||
'%s changed the assignee of the task %s to %s' => '%s a changé la personne assignée sur la tâche %s pour %s',
|
'%s changed the assignee of the task %s to %s' => '%s a changé la personne assignée à la tâche %s pour %s',
|
||||||
'New password for the user "%s"' => 'Nouveau mot de passe pour l\'utilisateur « %s »',
|
'New password for the user "%s"' => 'Nouveau mot de passe pour l\'utilisateur « %s »',
|
||||||
'Choose an event' => 'Choisir un événement',
|
'Choose an event' => 'Choisir un événement',
|
||||||
'Github commit received' => 'Commit reçu via Github',
|
'Github commit received' => 'Commit reçu via Github',
|
||||||
|
@ -466,7 +464,7 @@ return array(
|
||||||
'Reference: %s' => 'Référence : %s',
|
'Reference: %s' => 'Référence : %s',
|
||||||
'Label' => 'Libellé',
|
'Label' => 'Libellé',
|
||||||
'Database' => 'Base de données',
|
'Database' => 'Base de données',
|
||||||
'About' => 'A propos',
|
'About' => 'À propos',
|
||||||
'Database driver:' => 'Type de base de données :',
|
'Database driver:' => 'Type de base de données :',
|
||||||
'Board settings' => 'Paramètres du tableau',
|
'Board settings' => 'Paramètres du tableau',
|
||||||
'URL and token' => 'URL et jeton de sécurité',
|
'URL and token' => 'URL et jeton de sécurité',
|
||||||
|
@ -529,12 +527,12 @@ return array(
|
||||||
'Previous' => 'Précédent',
|
'Previous' => 'Précédent',
|
||||||
'The id must be an integer' => 'L\'id doit être un entier',
|
'The id must be an integer' => 'L\'id doit être un entier',
|
||||||
'The project id must be an integer' => 'L\'id du projet doit être un entier',
|
'The project id must be an integer' => 'L\'id du projet doit être un entier',
|
||||||
'The status must be an integer' => 'Le status doit être un entier',
|
'The status must be an integer' => 'Le statut doit être un entier',
|
||||||
'The subtask id is required' => 'L\'id de la sous-tâche est obligatoire',
|
'The subtask id is required' => 'L\'id de la sous-tâche est obligatoire',
|
||||||
'The subtask id must be an integer' => 'L\'id de la sous-tâche doit être en entier',
|
'The subtask id must be an integer' => 'L\'id de la sous-tâche doit être un entier',
|
||||||
'The task id is required' => 'L\'id de la tâche est obligatoire',
|
'The task id is required' => 'L\'id de la tâche est obligatoire',
|
||||||
'The task id must be an integer' => 'L\'id de la tâche doit être en entier',
|
'The task id must be an integer' => 'L\'id de la tâche doit être un entier',
|
||||||
'The user id must be an integer' => 'L\'id de l\'utilisateur doit être en entier',
|
'The user id must be an integer' => 'L\'id de l\'utilisateur doit être un entier',
|
||||||
'This value is required' => 'Cette valeur est obligatoire',
|
'This value is required' => 'Cette valeur est obligatoire',
|
||||||
'This value must be numeric' => 'Cette valeur doit être numérique',
|
'This value must be numeric' => 'Cette valeur doit être numérique',
|
||||||
'Unable to create this task.' => 'Impossible de créer cette tâche',
|
'Unable to create this task.' => 'Impossible de créer cette tâche',
|
||||||
|
@ -552,7 +550,7 @@ return array(
|
||||||
'Add a new swimlane' => 'Ajouter une nouvelle swimlane',
|
'Add a new swimlane' => 'Ajouter une nouvelle swimlane',
|
||||||
'Change default swimlane' => 'Modifier la swimlane par défaut',
|
'Change default swimlane' => 'Modifier la swimlane par défaut',
|
||||||
'Default swimlane' => 'Swimlane par défaut',
|
'Default swimlane' => 'Swimlane par défaut',
|
||||||
'Do you really want to remove this swimlane: "%s"?' => 'Voulez-vous vraiment supprimer cette swimlane : « %s » ?',
|
'Do you really want to remove this swimlane: "%s"?' => 'Voulez-vous vraiment supprimer cette swimlane : « %s » ?',
|
||||||
'Inactive swimlanes' => 'Swimlanes inactives',
|
'Inactive swimlanes' => 'Swimlanes inactives',
|
||||||
'Set project manager' => 'Mettre chef de projet',
|
'Set project manager' => 'Mettre chef de projet',
|
||||||
'Set project member' => 'Mettre membre du projet',
|
'Set project member' => 'Mettre membre du projet',
|
||||||
|
@ -570,7 +568,7 @@ return array(
|
||||||
'Unable to update this swimlane.' => 'Impossible de mettre à jour cette swimlane.',
|
'Unable to update this swimlane.' => 'Impossible de mettre à jour cette swimlane.',
|
||||||
'Your swimlane have been created successfully.' => 'Votre swimlane a été créée avec succès.',
|
'Your swimlane have been created successfully.' => 'Votre swimlane a été créée avec succès.',
|
||||||
'Example: "Bug, Feature Request, Improvement"' => 'Exemple: « Incident, Demande de fonctionnalité, Amélioration »',
|
'Example: "Bug, Feature Request, Improvement"' => 'Exemple: « Incident, Demande de fonctionnalité, Amélioration »',
|
||||||
'Default categories for new projects (Comma-separated)' => 'Catégories par défaut pour les nouveaux projets (séparé par des virgules)',
|
'Default categories for new projects (Comma-separated)' => 'Catégories par défaut pour les nouveaux projets (séparation par des virgules)',
|
||||||
'Gitlab commit received' => 'Commit reçu via Gitlab',
|
'Gitlab commit received' => 'Commit reçu via Gitlab',
|
||||||
'Gitlab issue opened' => 'Ouverture d\'un ticket sur Gitlab',
|
'Gitlab issue opened' => 'Ouverture d\'un ticket sur Gitlab',
|
||||||
'Gitlab issue closed' => 'Fermeture d\'un ticket sur Gitlab',
|
'Gitlab issue closed' => 'Fermeture d\'un ticket sur Gitlab',
|
||||||
|
@ -604,25 +602,25 @@ return array(
|
||||||
'User dashboard' => 'Tableau de bord de l\'utilisateur',
|
'User dashboard' => 'Tableau de bord de l\'utilisateur',
|
||||||
'Allow only one subtask in progress at the same time for a user' => 'Autoriser une seule sous-tâche en progrès en même temps pour un utilisateur',
|
'Allow only one subtask in progress at the same time for a user' => 'Autoriser une seule sous-tâche en progrès en même temps pour un utilisateur',
|
||||||
'Edit column "%s"' => 'Modifier la colonne « %s »',
|
'Edit column "%s"' => 'Modifier la colonne « %s »',
|
||||||
'Select the new status of the subtask: "%s"' => 'Selectionnez le nouveau statut de la sous-tâche : « %s »',
|
'Select the new status of the subtask: "%s"' => 'Selectionnez le nouveau statut de la sous-tâche : « %s »',
|
||||||
'Subtask timesheet' => 'Feuille de temps des sous-tâches',
|
'Subtask timesheet' => 'Feuille de temps des sous-tâches',
|
||||||
'There is nothing to show.' => 'Il n\'y a rien à montrer.',
|
'There is nothing to show.' => 'Il n\'y a rien à montrer.',
|
||||||
'Time Tracking' => 'Feuille de temps',
|
'Time Tracking' => 'Feuille de temps',
|
||||||
'You already have one subtask in progress' => 'Vous avez déjà une sous-tâche en progrès',
|
'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 ?',
|
'Which parts of the project do you want to duplicate?' => 'Quelles parties du projet voulez-vous dupliquer ?',
|
||||||
'Disallow login form' => 'Interdir le formulaire d\'authentification',
|
'Disallow login form' => 'Interdire le formulaire d\'authentification',
|
||||||
'Bitbucket commit received' => 'Commit reçu via Bitbucket',
|
'Bitbucket commit received' => 'Commit reçu via Bitbucket',
|
||||||
'Bitbucket webhooks' => 'Webhook Bitbucket',
|
'Bitbucket webhooks' => 'Webhook Bitbucket',
|
||||||
'Help on Bitbucket webhooks' => 'Aide sur les webhooks Bitbucket',
|
'Help on Bitbucket webhooks' => 'Aide sur les webhooks Bitbucket',
|
||||||
'Start' => 'Début',
|
'Start' => 'Début',
|
||||||
'End' => 'Fin',
|
'End' => 'Fin',
|
||||||
'Task age in days' => 'Age de la tâche en jours',
|
'Task age in days' => 'Âge de la tâche en jours',
|
||||||
'Days in this column' => 'Jours dans cette colonne',
|
'Days in this column' => 'Jours dans cette colonne',
|
||||||
'%dd' => '%dj',
|
'%dd' => '%dj',
|
||||||
'Add a link' => 'Ajouter un lien',
|
'Add a link' => 'Ajouter un lien',
|
||||||
'Add a new link' => 'Ajouter un nouveau lien',
|
'Add a new link' => 'Ajouter un nouveau lien',
|
||||||
'Do you really want to remove this link: "%s"?' => 'Voulez-vous vraiment supprimer ce lien : « %s » ?',
|
'Do you really want to remove this link: "%s"?' => 'Voulez-vous vraiment supprimer ce lien : « %s » ?',
|
||||||
'Do you really want to remove this link with task #%d?' => 'Voulez-vous vraiment supprimer ce lien avec la tâche n°%d ?',
|
'Do you really want to remove this link with task #%d?' => 'Voulez-vous vraiment supprimer ce lien avec la tâche n°%d ?',
|
||||||
'Field required' => 'Champ obligatoire',
|
'Field required' => 'Champ obligatoire',
|
||||||
'Link added successfully.' => 'Lien créé avec succès.',
|
'Link added successfully.' => 'Lien créé avec succès.',
|
||||||
'Link updated successfully.' => 'Lien mis à jour avec succès.',
|
'Link updated successfully.' => 'Lien mis à jour avec succès.',
|
||||||
|
@ -658,7 +656,7 @@ return array(
|
||||||
'Expand tasks' => 'Déplier les tâches',
|
'Expand tasks' => 'Déplier les tâches',
|
||||||
'Collapse tasks' => 'Replier les tâches',
|
'Collapse tasks' => 'Replier les tâches',
|
||||||
'Expand/collapse tasks' => 'Plier/déplier les tâches',
|
'Expand/collapse tasks' => 'Plier/déplier les tâches',
|
||||||
'Close dialog box' => 'Fermer une boite de dialogue',
|
'Close dialog box' => 'Fermer une boîte de dialogue',
|
||||||
'Submit a form' => 'Enregistrer un formulaire',
|
'Submit a form' => 'Enregistrer un formulaire',
|
||||||
'Board view' => 'Page du tableau',
|
'Board view' => 'Page du tableau',
|
||||||
'Keyboard shortcuts' => 'Raccourcis clavier',
|
'Keyboard shortcuts' => 'Raccourcis clavier',
|
||||||
|
@ -669,75 +667,26 @@ return array(
|
||||||
'Horizontal scrolling' => 'Défilement horizontal',
|
'Horizontal scrolling' => 'Défilement horizontal',
|
||||||
'Compact/wide view' => 'Basculer entre la vue compacte et étendue',
|
'Compact/wide view' => 'Basculer entre la vue compacte et étendue',
|
||||||
'No results match:' => 'Aucun résultat :',
|
'No results match:' => 'Aucun résultat :',
|
||||||
'Remove hourly rate' => 'Supprimer un taux horaire',
|
|
||||||
'Do you really want to remove this hourly rate?' => 'Voulez-vous vraiment supprimer ce taux horaire ?',
|
|
||||||
'Hourly rates' => 'Taux horaires',
|
|
||||||
'Hourly rate' => 'Taux horaire',
|
|
||||||
'Currency' => 'Devise',
|
'Currency' => 'Devise',
|
||||||
'Effective date' => 'Date d\'effet',
|
|
||||||
'Add new rate' => 'Ajouter un nouveau taux horaire',
|
|
||||||
'Rate removed successfully.' => 'Taux horaire supprimé avec succès.',
|
|
||||||
'Unable to remove this rate.' => 'Impossible de supprimer ce taux horaire.',
|
|
||||||
'Unable to save the hourly rate.' => 'Impossible de sauvegarder ce taux horaire.',
|
|
||||||
'Hourly rate created successfully.' => 'Taux horaire créé avec succès.',
|
|
||||||
'Start time' => 'Date de début',
|
|
||||||
'End time' => 'Date de fin',
|
|
||||||
'Comment' => 'Commentaire',
|
|
||||||
'All day' => 'Toute la journée',
|
|
||||||
'Day' => 'Jour',
|
|
||||||
'Manage timetable' => 'Gérer les horaires',
|
|
||||||
'Overtime timetable' => 'Heures supplémentaires',
|
|
||||||
'Time off timetable' => 'Heures d\'absences',
|
|
||||||
'Timetable' => 'Horaires',
|
|
||||||
'Work timetable' => 'Horaires travaillés',
|
|
||||||
'Week timetable' => 'Horaires de la semaine',
|
|
||||||
'Day timetable' => 'Horaire d\'une journée',
|
|
||||||
'From' => 'Depuis',
|
|
||||||
'To' => 'À',
|
|
||||||
'Time slot created successfully.' => 'Créneau horaire créé avec succès.',
|
|
||||||
'Unable to save this time slot.' => 'Impossible de sauvegarder ce créneau horaire.',
|
|
||||||
'Time slot removed successfully.' => 'Créneau horaire supprimé avec succès.',
|
|
||||||
'Unable to remove this time slot.' => 'Impossible de supprimer ce créneau horaire.',
|
|
||||||
'Do you really want to remove this time slot?' => 'Voulez-vous vraiment supprimer ce créneau horaire ?',
|
|
||||||
'Remove time slot' => 'Supprimer un créneau horaire',
|
|
||||||
'Add new time slot' => 'Ajouter un créneau horaire',
|
|
||||||
'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => 'Ces horaires sont utilisés lorsque la case « Toute la journée » est cochée pour les heures d\'absences ou supplémentaires programmées.',
|
|
||||||
'Files' => 'Fichiers',
|
'Files' => 'Fichiers',
|
||||||
'Images' => 'Images',
|
'Images' => 'Images',
|
||||||
'Private project' => 'Projet privé',
|
'Private project' => 'Projet privé',
|
||||||
'Amount' => 'Montant',
|
|
||||||
'AUD - Australian Dollar' => 'AUD - Dollar australien',
|
'AUD - Australian Dollar' => 'AUD - Dollar australien',
|
||||||
'Budget' => 'Budget',
|
|
||||||
'Budget line' => 'Ligne budgétaire',
|
|
||||||
'Budget line removed successfully.' => 'Ligne budgétaire supprimée avec succès.',
|
|
||||||
'Budget lines' => 'Lignes budgétaire',
|
|
||||||
'CAD - Canadian Dollar' => 'CAD - Dollar canadien',
|
'CAD - Canadian Dollar' => 'CAD - Dollar canadien',
|
||||||
'CHF - Swiss Francs' => 'CHF - Franc suisse',
|
'CHF - Swiss Francs' => 'CHF - Franc suisse',
|
||||||
'Cost' => 'Coût',
|
|
||||||
'Cost breakdown' => 'Détail des coûts',
|
|
||||||
'Custom Stylesheet' => 'Feuille de style personalisée',
|
'Custom Stylesheet' => 'Feuille de style personalisée',
|
||||||
'download' => 'télécharger',
|
'download' => 'télécharger',
|
||||||
'Do you really want to remove this budget line?' => 'Voulez-vous vraiment supprimer cette ligne budgétaire ?',
|
|
||||||
'EUR - Euro' => 'EUR - Euro',
|
'EUR - Euro' => 'EUR - Euro',
|
||||||
'Expenses' => 'Dépenses',
|
|
||||||
'GBP - British Pound' => 'GBP - Livre sterling',
|
'GBP - British Pound' => 'GBP - Livre sterling',
|
||||||
'INR - Indian Rupee' => 'INR - Roupie indienne',
|
'INR - Indian Rupee' => 'INR - Roupie indienne',
|
||||||
'JPY - Japanese Yen' => 'JPY - Yen',
|
'JPY - Japanese Yen' => 'JPY - Yen',
|
||||||
'New budget line' => 'Nouvelle ligne budgétaire',
|
|
||||||
'NZD - New Zealand Dollar' => 'NZD - Dollar néo-zélandais',
|
'NZD - New Zealand Dollar' => 'NZD - Dollar néo-zélandais',
|
||||||
'Remove a budget line' => 'Supprimer une ligne budgétaire',
|
|
||||||
'Remove budget line' => 'Supprimer une ligne budgétaire',
|
|
||||||
'RSD - Serbian dinar' => 'RSD - Dinar serbe',
|
'RSD - Serbian dinar' => 'RSD - Dinar serbe',
|
||||||
'The budget line have been created successfully.' => 'La ligne de budgétaire a été créée avec succès.',
|
|
||||||
'Unable to create the budget line.' => 'Impossible de créer cette ligne budgétaire.',
|
|
||||||
'Unable to remove this budget line.' => 'Impossible de supprimer cette ligne budgétaire.',
|
|
||||||
'USD - US Dollar' => 'USD - Dollar américain',
|
'USD - US Dollar' => 'USD - Dollar américain',
|
||||||
'Remaining' => 'Restant',
|
|
||||||
'Destination column' => 'Colonne de destination',
|
'Destination column' => 'Colonne de destination',
|
||||||
'Move the task to another column when assigned to a user' => 'Déplacer la tâche dans une autre colonne lorsque celle-ci est assignée à quelqu\'un',
|
'Move the task to another column when assigned to a user' => 'Déplacer la tâche dans une autre colonne lorsque celle-ci est assignée à quelqu\'un',
|
||||||
'Move the task to another column when assignee is cleared' => 'Déplacer la tâche dans une autre colonne lorsque celle-ci n\'est plus assignée',
|
'Move the task to another column when assignee is cleared' => 'Déplacer la tâche dans une autre colonne lorsque celle-ci n\'est plus assignée',
|
||||||
'Source column' => 'Colonne d\'origine',
|
'Source column' => 'Colonne d\'origine',
|
||||||
'Show subtask estimates (forecast of future work)' => 'Afficher l\'estimation des sous-tâches (prévision du travail à venir)',
|
|
||||||
'Transitions' => 'Transitions',
|
'Transitions' => 'Transitions',
|
||||||
'Executer' => 'Exécutant',
|
'Executer' => 'Exécutant',
|
||||||
'Time spent in the column' => 'Temps passé dans la colonne',
|
'Time spent in the column' => 'Temps passé dans la colonne',
|
||||||
|
@ -748,7 +697,6 @@ return array(
|
||||||
'Rate' => 'Taux',
|
'Rate' => 'Taux',
|
||||||
'Change reference currency' => 'Changer la monnaie de référence',
|
'Change reference currency' => 'Changer la monnaie de référence',
|
||||||
'Add a new currency rate' => 'Ajouter un nouveau taux pour une devise',
|
'Add a new currency rate' => 'Ajouter un nouveau taux pour une devise',
|
||||||
'Currency rates are used to calculate project budget.' => 'Le cours des devises est utilisé pour calculer le budget des projets.',
|
|
||||||
'Reference currency' => 'Devise de référence',
|
'Reference currency' => 'Devise de référence',
|
||||||
'The currency rate have been added successfully.' => 'Le taux de change a été ajouté avec succès.',
|
'The currency rate have been added successfully.' => 'Le taux de change a été ajouté avec succès.',
|
||||||
'Unable to add this currency rate.' => 'Impossible d\'ajouter ce taux de change',
|
'Unable to add this currency rate.' => 'Impossible d\'ajouter ce taux de change',
|
||||||
|
@ -769,8 +717,8 @@ return array(
|
||||||
'Code' => 'Code',
|
'Code' => 'Code',
|
||||||
'Two factor authentication' => 'Authentification à deux-facteurs',
|
'Two factor authentication' => 'Authentification à deux-facteurs',
|
||||||
'Enable/disable two factor authentication' => 'Activer/désactiver l\'authentification à deux-facteurs',
|
'Enable/disable two factor authentication' => 'Activer/désactiver l\'authentification à deux-facteurs',
|
||||||
'This QR code contains the key URI: ' => 'Ce code QR contient l\'url de la clé : ',
|
'This QR code contains the key URI: ' => 'Ce code QR contient l\'url de la clé : ',
|
||||||
'Save the secret key in your TOTP software (by example Google Authenticator or FreeOTP).' => 'Sauvegardez cette clé secrete dans votre logiciel TOTP (par exemple Google Authenticator ou FreeOTP).',
|
'Save the secret key in your TOTP software (by example Google Authenticator or FreeOTP).' => 'Sauvegardez cette clé secrète dans votre logiciel TOTP (par exemple Google Authenticator ou FreeOTP).',
|
||||||
'Check my code' => 'Vérifier mon code',
|
'Check my code' => 'Vérifier mon code',
|
||||||
'Secret key: ' => 'Clé secrète : ',
|
'Secret key: ' => 'Clé secrète : ',
|
||||||
'Test your device' => 'Testez votre appareil',
|
'Test your device' => 'Testez votre appareil',
|
||||||
|
@ -796,9 +744,9 @@ return array(
|
||||||
'Sendgrid (incoming emails)' => 'Sendgrid (emails entrants)',
|
'Sendgrid (incoming emails)' => 'Sendgrid (emails entrants)',
|
||||||
'Help on Sendgrid integration' => 'Aide sur l\'intégration avec Sendgrid',
|
'Help on Sendgrid integration' => 'Aide sur l\'intégration avec Sendgrid',
|
||||||
'Disable two factor authentication' => 'Désactiver l\'authentification à deux facteurs',
|
'Disable two factor authentication' => 'Désactiver l\'authentification à deux facteurs',
|
||||||
'Do you really want to disable the two factor authentication for this user: "%s"?' => 'Voulez-vous vraiment désactiver l\'authentification à deux facteurs pour cet utilisateur : « %s » ?',
|
'Do you really want to disable the two factor authentication for this user: "%s"?' => 'Voulez-vous vraiment désactiver l\'authentification à deux facteurs pour cet utilisateur : « %s » ?',
|
||||||
'Edit link' => 'Modifier un lien',
|
'Edit link' => 'Modifier un lien',
|
||||||
'Start to type task title...' => 'Entrez le titre de la tâche...',
|
'Start to type task title...' => 'Entrez le titre de la tâche…',
|
||||||
'A task cannot be linked to itself' => 'Une tâche ne peut être liée à elle-même',
|
'A task cannot be linked to itself' => 'Une tâche ne peut être liée à elle-même',
|
||||||
'The exact same link already exists' => 'Un lien identique existe déjà',
|
'The exact same link already exists' => 'Un lien identique existe déjà',
|
||||||
'Recurrent task is scheduled to be generated' => 'La tâche récurrente est programmée pour être créée',
|
'Recurrent task is scheduled to be generated' => 'La tâche récurrente est programmée pour être créée',
|
||||||
|
@ -814,17 +762,17 @@ return array(
|
||||||
'Timeframe to calculate new due date' => 'Échelle de temps pour calculer la nouvelle date d\'échéance',
|
'Timeframe to calculate new due date' => 'Échelle de temps pour calculer la nouvelle date d\'échéance',
|
||||||
'Base date to calculate new due date' => 'Date à utiliser pour calculer la nouvelle date d\'échéance',
|
'Base date to calculate new due date' => 'Date à utiliser pour calculer la nouvelle date d\'échéance',
|
||||||
'Action date' => 'Date de l\'action',
|
'Action date' => 'Date de l\'action',
|
||||||
'Base date to calculate new due date: ' => 'Date utilisée pour calculer la nouvelle date d\'échéance : ',
|
'Base date to calculate new due date: ' => 'Date utilisée pour calculer la nouvelle date d\'échéance : ',
|
||||||
'This task has created this child task: ' => 'Cette tâche a créée la tâche enfant : ',
|
'This task has created this child task: ' => 'Cette tâche a créée la tâche enfant : ',
|
||||||
'Day(s)' => 'Jour(s)',
|
'Day(s)' => 'Jour(s)',
|
||||||
'Existing due date' => 'Date d\'échéance existante',
|
'Existing due date' => 'Date d\'échéance existante',
|
||||||
'Factor to calculate new due date: ' => 'Facteur pour calculer la nouvelle date d\'échéance : ',
|
'Factor to calculate new due date: ' => 'Facteur pour calculer la nouvelle date d\'échéance : ',
|
||||||
'Month(s)' => 'Mois',
|
'Month(s)' => 'Mois',
|
||||||
'Recurrence' => 'Récurrence',
|
'Recurrence' => 'Récurrence',
|
||||||
'This task has been created by: ' => 'Cette tâche a été créée par :',
|
'This task has been created by: ' => 'Cette tâche a été créée par :',
|
||||||
'Recurrent task has been generated:' => 'Une tâche récurrente a été générée :',
|
'Recurrent task has been generated:' => 'Une tâche récurrente a été générée :',
|
||||||
'Timeframe to calculate new due date: ' => 'Échelle de temps pour calculer la nouvelle date d\'échéance : ',
|
'Timeframe to calculate new due date: ' => 'Échelle de temps pour calculer la nouvelle date d\'échéance : ',
|
||||||
'Trigger to generate recurrent task: ' => 'Déclencheur pour générer la tâche récurrente : ',
|
'Trigger to generate recurrent task: ' => 'Déclencheur pour générer la tâche récurrente : ',
|
||||||
'When task is closed' => 'Lorsque la tâche est fermée',
|
'When task is closed' => 'Lorsque la tâche est fermée',
|
||||||
'When task is moved from first column' => 'Lorsque la tâche est déplacée en dehors de la première colonne',
|
'When task is moved from first column' => 'Lorsque la tâche est déplacée en dehors de la première colonne',
|
||||||
'When task is moved to last column' => 'Lorsque la tâche est déplacée dans la dernière colonne',
|
'When task is moved to last column' => 'Lorsque la tâche est déplacée dans la dernière colonne',
|
||||||
|
@ -836,7 +784,7 @@ return array(
|
||||||
'Jabber nickname' => 'Pseudonyme Jabber',
|
'Jabber nickname' => 'Pseudonyme Jabber',
|
||||||
'Multi-user chat room' => 'Salon de discussion multi-utilisateurs',
|
'Multi-user chat room' => 'Salon de discussion multi-utilisateurs',
|
||||||
'Help on Jabber integration' => 'Aide sur l\'intégration avec Jabber',
|
'Help on Jabber integration' => 'Aide sur l\'intégration avec Jabber',
|
||||||
'The server address must use this format: "tcp://hostname:5222"' => 'L\'adresse du serveur doit utiliser le format suivant : « tcp://hostname:5222 »',
|
'The server address must use this format: "tcp://hostname:5222"' => 'L\'adresse du serveur doit utiliser le format suivant : « tcp://hostname:5222 »',
|
||||||
'Calendar settings' => 'Paramètres du calendrier',
|
'Calendar settings' => 'Paramètres du calendrier',
|
||||||
'Project calendar view' => 'Vue en mode projet du calendrier',
|
'Project calendar view' => 'Vue en mode projet du calendrier',
|
||||||
'Project settings' => 'Paramètres du projet',
|
'Project settings' => 'Paramètres du projet',
|
||||||
|
@ -849,7 +797,7 @@ return array(
|
||||||
'iCal feed' => 'Abonnement iCal',
|
'iCal feed' => 'Abonnement iCal',
|
||||||
'Preferences' => 'Préférences',
|
'Preferences' => 'Préférences',
|
||||||
'Security' => 'Sécurité',
|
'Security' => 'Sécurité',
|
||||||
'Two factor authentication disabled' => 'Authentification à deux facteurs désactivé',
|
'Two factor authentication disabled' => 'Authentification à deux facteurs désactivée',
|
||||||
'Two factor authentication enabled' => 'Authentification à deux facteurs activée',
|
'Two factor authentication enabled' => 'Authentification à deux facteurs activée',
|
||||||
'Unable to update this user.' => 'Impossible de mettre à jour cet utilisateur.',
|
'Unable to update this user.' => 'Impossible de mettre à jour cet utilisateur.',
|
||||||
'There is no user management for private projects.' => 'Il n\'y a pas de gestion d\'utilisateurs pour les projets privés.',
|
'There is no user management for private projects.' => 'Il n\'y a pas de gestion d\'utilisateurs pour les projets privés.',
|
||||||
|
@ -862,8 +810,8 @@ return array(
|
||||||
'Commit made by @%s on Github' => 'Commit fait par @%s sur Github',
|
'Commit made by @%s on Github' => 'Commit fait par @%s sur Github',
|
||||||
'By @%s on Github' => 'Par @%s sur Github',
|
'By @%s on Github' => 'Par @%s sur Github',
|
||||||
'Commit made by @%s on Gitlab' => 'Commit fait par @%s sur Gitlab',
|
'Commit made by @%s on Gitlab' => 'Commit fait par @%s sur Gitlab',
|
||||||
'Add a comment log when moving the task between columns' => 'Ajouter un commentaire d\'information lorsque une tâche est déplacée dans une autre colonnes',
|
'Add a comment log when moving the task between columns' => 'Ajouter un commentaire d\'information lorsque une tâche est déplacée dans une autre colonne',
|
||||||
'Move the task to another column when the category is changed' => 'Déplacer une tâche vers une autre colonne lorsque la catégorie a changée',
|
'Move the task to another column when the category is changed' => 'Déplacer une tâche vers une autre colonne lorsque la catégorie a changé',
|
||||||
'Send a task by email to someone' => 'Envoyer une tâche par email à quelqu\'un',
|
'Send a task by email to someone' => 'Envoyer une tâche par email à quelqu\'un',
|
||||||
'Reopen a task' => 'Rouvrir une tâche',
|
'Reopen a task' => 'Rouvrir une tâche',
|
||||||
'Bitbucket issue opened' => 'Ticket Bitbucket ouvert',
|
'Bitbucket issue opened' => 'Ticket Bitbucket ouvert',
|
||||||
|
@ -880,16 +828,13 @@ return array(
|
||||||
'%s moved the task #%d to the first swimlane' => '%s a déplacé la tâche n°%d dans la première swimlane',
|
'%s moved the task #%d to the first swimlane' => '%s a déplacé la tâche n°%d dans la première swimlane',
|
||||||
'%s moved the task #%d to the swimlane "%s"' => '%s a déplacé la tâche n°%d dans la swimlane « %s »',
|
'%s moved the task #%d to the swimlane "%s"' => '%s a déplacé la tâche n°%d dans la swimlane « %s »',
|
||||||
'Swimlane' => 'Swimlane',
|
'Swimlane' => 'Swimlane',
|
||||||
'Budget overview' => 'Vue d\'ensemble du budget',
|
|
||||||
'Type' => 'Type',
|
|
||||||
'There is not enough data to show something.' => 'Il n\'y a pas assez de données pour montrer quelque chose.',
|
|
||||||
'Gravatar' => 'Gravatar',
|
'Gravatar' => 'Gravatar',
|
||||||
'Hipchat' => 'Hipchat',
|
'Hipchat' => 'Hipchat',
|
||||||
'Slack' => 'Slack',
|
'Slack' => 'Slack',
|
||||||
'%s moved the task %s to the first swimlane' => '%s a déplacé la tâche %s dans la première swimlane',
|
'%s moved the task %s to the first swimlane' => '%s a déplacé la tâche %s dans la première swimlane',
|
||||||
'%s moved the task %s to the swimlane "%s"' => '%s a déplacé la tâche %s dans la swimlane « %s »',
|
'%s moved the task %s to the swimlane "%s"' => '%s a déplacé la tâche %s dans la swimlane « %s »',
|
||||||
'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 subtasks information for the given date range.' => 'Ce rapport contient les informations de toutes les sous-tâches pour la période sélectionné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.',
|
'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 sélectionnée.',
|
||||||
'Project activities for %s' => 'Activité des projets pour « %s »',
|
'Project activities for %s' => 'Activité des projets pour « %s »',
|
||||||
'view the board on Kanboard' => 'voir le 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 the first swimlane' => 'La tâche a été déplacée dans la première swimlane',
|
||||||
|
@ -907,15 +852,15 @@ return array(
|
||||||
'Recurrence settings have been modified' => 'Les réglages de la récurrence ont été modifiés',
|
'Recurrence settings have been modified' => 'Les réglages de la récurrence ont été modifiés',
|
||||||
'Time spent changed: %sh' => 'Le temps passé a été changé : %sh',
|
'Time spent changed: %sh' => 'Le temps passé a été changé : %sh',
|
||||||
'Time estimated changed: %sh' => 'Le temps estimé a été changé : %sh',
|
'Time estimated changed: %sh' => 'Le temps estimé a été changé : %sh',
|
||||||
'The field "%s" have been updated' => 'Le champ « %s » a été mis à jour',
|
'The field "%s" have been updated' => 'Le champ « %s » a été mis à jour',
|
||||||
'The description have been modified' => 'La description a été modifiée',
|
'The description have been modified' => 'La description a été modifiée',
|
||||||
'Do you really want to close the task "%s" as well as all subtasks?' => 'Voulez-vous vraiment fermer la tâche « %s » ainsi que toutes ses sous-tâches ?',
|
'Do you really want to close the task "%s" as well as all subtasks?' => 'Voulez-vous vraiment fermer la tâche « %s » ainsi que toutes ses sous-tâches ?',
|
||||||
'Swimlane: %s' => 'Swimlane : %s',
|
'Swimlane: %s' => 'Swimlane : %s',
|
||||||
'I want to receive notifications for:' => 'Je veux reçevoir les notifications pour :',
|
'I want to receive notifications for:' => 'Je veux reçevoir les notifications pour :',
|
||||||
'All tasks' => 'Toutes les Tâches',
|
'All tasks' => 'Toutes les Tâches',
|
||||||
'Only for tasks assigned to me' => 'Seulement les tâches qui me sont assignées',
|
'Only for tasks assigned to me' => 'Seulement les tâches qui me sont assignées',
|
||||||
'Only for tasks created by me' => 'Seulement les tâches que j\'ai créées',
|
'Only for tasks created by me' => 'Seulement les tâches que j\'ai créées',
|
||||||
'Only for tasks created by me and assigned to me' => 'Seulement les tâches créées par moi-même et celles qui me sont asignées',
|
'Only for tasks created by me and assigned to me' => 'Seulement les tâches créées par moi-même et celles qui me sont assignées',
|
||||||
'%A' => '%A',
|
'%A' => '%A',
|
||||||
'%b %e, %Y, %k:%M %p' => '%d/%m/%Y %H:%M',
|
'%b %e, %Y, %k:%M %p' => '%d/%m/%Y %H:%M',
|
||||||
'New due date: %B %e, %Y' => 'Nouvelle date d\'échéance : %d/%m/%Y',
|
'New due date: %B %e, %Y' => 'Nouvelle date d\'échéance : %d/%m/%Y',
|
||||||
|
@ -995,7 +940,7 @@ return array(
|
||||||
'Github Id' => 'Identifiant Github',
|
'Github Id' => 'Identifiant Github',
|
||||||
'Remote user' => 'Utilisateur distant',
|
'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.',
|
'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.',
|
'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => 'Si vous cochez la case « Interdire le formulaire d\'authentification », les identifiants entrés dans le formulaire d\'authentification seront ignorés.',
|
||||||
'By @%s on Gitlab' => 'Par @%s sur Gitlab',
|
'By @%s on Gitlab' => 'Par @%s sur Gitlab',
|
||||||
'Gitlab issue comment created' => 'Commentaire créé sur un ticket Gitlab',
|
'Gitlab issue comment created' => 'Commentaire créé sur un ticket Gitlab',
|
||||||
'New remote user' => 'Créer un utilisateur distant',
|
'New remote user' => 'Créer un utilisateur distant',
|
||||||
|
@ -1023,14 +968,14 @@ return array(
|
||||||
'Sort by position' => 'Trier par position',
|
'Sort by position' => 'Trier par position',
|
||||||
'Sort by date' => 'Trier par date',
|
'Sort by date' => 'Trier par date',
|
||||||
'Add task' => 'Ajouter une tâche',
|
'Add task' => 'Ajouter une tâche',
|
||||||
'Start date:' => 'Date de début :',
|
'Start date:' => 'Date de début :',
|
||||||
'Due date:' => 'Date d\'échéance :',
|
'Due date:' => 'Date d\'échéance :',
|
||||||
'There is no start date or due date for this task.' => 'Il n\'y a pas de date de début ou de date de fin pour cette tâche.',
|
'There is no start date or due date for this task.' => 'Il n\'y a pas de date de début ou de date de fin pour cette tâche.',
|
||||||
'Moving or resizing a task will change the start and due date of the task.' => 'Déplacer ou redimensionner une tâche va changer la date de début et la date de fin de la tâche.',
|
'Moving or resizing a task will change the start and due date of the task.' => 'Déplacer ou redimensionner une tâche va changer la date de début et la date de fin de la tâche.',
|
||||||
'There is no task in your project.' => 'Il n\'y a aucun tâche dans votre projet.',
|
'There is no task in your project.' => 'Il n\'y a aucune tâche dans votre projet.',
|
||||||
'Gantt chart' => 'Diagramme de Gantt',
|
'Gantt chart' => 'Diagramme de Gantt',
|
||||||
'People who are project managers' => 'Personnes qui sont gestionnaire de projet',
|
'People who are project managers' => 'Personnes qui sont gestionnaires de projet',
|
||||||
'People who are project members' => 'Personnes qui sont membre de projet',
|
'People who are project members' => 'Personnes qui sont membres de projet',
|
||||||
'NOK - Norwegian Krone' => 'NOK - Couronne norvégienne',
|
'NOK - Norwegian Krone' => 'NOK - Couronne norvégienne',
|
||||||
'Show this column' => 'Montrer cette colonne',
|
'Show this column' => 'Montrer cette colonne',
|
||||||
'Hide this column' => 'Cacher cette colonne',
|
'Hide this column' => 'Cacher cette colonne',
|
||||||
|
@ -1043,14 +988,14 @@ return array(
|
||||||
'Project managers' => 'Gestionnaires de projet',
|
'Project managers' => 'Gestionnaires de projet',
|
||||||
'Project members' => 'Membres de projet',
|
'Project members' => 'Membres de projet',
|
||||||
'Gantt chart for all projects' => 'Diagramme de Gantt pour tous les projets',
|
'Gantt chart for all projects' => 'Diagramme de Gantt pour tous les projets',
|
||||||
'Projects list' => 'List des projets',
|
'Projects list' => 'Liste des projets',
|
||||||
'Gantt chart for this project' => 'Diagramme de Gantt pour ce projet',
|
'Gantt chart for this project' => 'Diagramme de Gantt pour ce projet',
|
||||||
'Project board' => 'Tableau du projet',
|
'Project board' => 'Tableau du projet',
|
||||||
'End date:' => 'Date de fin :',
|
'End date:' => 'Date de fin :',
|
||||||
'There is no start date or end date for this project.' => 'Il n\'y a pas de date de début ou de date de fin pour ce projet.',
|
'There is no start date or end date for this project.' => 'Il n\'y a pas de date de début ou de date de fin pour ce projet.',
|
||||||
'Projects Gantt chart' => 'Diagramme de Gantt des projets',
|
'Projects Gantt chart' => 'Diagramme de Gantt des projets',
|
||||||
'Start date: %s' => 'Date de début : %s',
|
'Start date: %s' => 'Date de début : %s',
|
||||||
'End date: %s' => 'Date de fin : %s',
|
'End date: %s' => 'Date de fin : %s',
|
||||||
'Link type' => 'Type de lien',
|
'Link type' => 'Type de lien',
|
||||||
'Change task color when using a specific task link' => 'Changer la couleur de la tâche lorsqu\'un lien spécifique est utilisé',
|
'Change task color when using a specific task link' => 'Changer la couleur de la tâche lorsqu\'un lien spécifique est utilisé',
|
||||||
'Task link creation or modification' => 'Création ou modification d\'un lien sur une tâche',
|
'Task link creation or modification' => 'Création ou modification d\'un lien sur une tâche',
|
||||||
|
@ -1069,4 +1014,48 @@ return array(
|
||||||
'Table of contents' => 'Table des matières',
|
'Table of contents' => 'Table des matières',
|
||||||
'Gantt' => 'Gantt',
|
'Gantt' => 'Gantt',
|
||||||
'Help with project permissions' => 'Aide avec les permissions des projets',
|
'Help with project permissions' => 'Aide avec les permissions des projets',
|
||||||
|
'Author' => 'Auteur',
|
||||||
|
'Version' => 'Version',
|
||||||
|
'Plugins' => 'Extensions',
|
||||||
|
'There is no plugin loaded.' => 'Il n\'y a aucune extension chargée.',
|
||||||
|
'Set maximum column height' => 'Définir la hauteur max. des colonnes',
|
||||||
|
'Remove maximum column height' => 'Enlever la hauteur max. des colonnes',
|
||||||
|
'My notifications' => 'Mes notifications',
|
||||||
|
'Custom filters' => 'Filtres personalisés',
|
||||||
|
'Your custom filter have been created successfully.' => 'Votre filter personalisé a été créé avec succès.',
|
||||||
|
'Unable to create your custom filter.' => 'Impossible de créer votre filter personalisé.',
|
||||||
|
'Custom filter removed successfully.' => 'Filtre personalisé supprimé avec succès.',
|
||||||
|
'Unable to remove this custom filter.' => 'Impossible de supprimer ce filter personalisé.',
|
||||||
|
'Edit custom filter' => 'Modification d\'un filtre personalisé',
|
||||||
|
'Your custom filter have been updated successfully.' => 'Votre filtre personalisé a été mis à jour avec succès.',
|
||||||
|
'Unable to update custom filter.' => 'Impossible de mettre à jour votre filtre personalisé.',
|
||||||
|
'Web' => 'Web',
|
||||||
|
'New attachment on task #%d: %s' => 'Nouveau fichier joint sur la tâche n°%d : %s',
|
||||||
|
'New comment on task #%d' => 'Nouveau commentaire sur la tâche n°%d',
|
||||||
|
'Comment updated on task #%d' => 'Commentaire mis à jour sur la tâche n°%d',
|
||||||
|
'New subtask on task #%d' => 'Nouvelle sous-tâche sur la tâche n°%d',
|
||||||
|
'Subtask updated on task #%d' => 'Sous-tâche mise à jour sur la tâche n°%d',
|
||||||
|
'New task #%d: %s' => 'Nouvelle tâche n°%d : %s',
|
||||||
|
'Task updated #%d' => 'Tâche n°%d mise à jour',
|
||||||
|
'Task #%d closed' => 'Tâche n°%d fermée',
|
||||||
|
'Task #%d opened' => 'Tâche n°%d ouverte',
|
||||||
|
'Column changed for task #%d' => 'Changement de colonne pour la tâche n°%d',
|
||||||
|
'New position for task #%d' => 'Nouvelle position pour la tâche n°%d',
|
||||||
|
'Swimlane changed for task #%d' => 'Changement de swimlane pour la tâche n°%d',
|
||||||
|
'Assignee changed on task #%d' => 'Changement de l\'assigné pour la tâche n°%d',
|
||||||
|
'%d overdue tasks' => '%d tâches en retard',
|
||||||
|
'Task #%d is overdue' => 'La tâche n°%d est retard',
|
||||||
|
'No new notifications.' => 'Aucune notification.',
|
||||||
|
'Mark all as read' => 'Tout marquer comme lu',
|
||||||
|
'Mark as read' => 'Marquer comme lu',
|
||||||
|
'Total number of tasks in this column across all swimlanes' => 'Nombre total de tâches dans cette colonne pour toutes les swimlanes',
|
||||||
|
'Collapse swimlane' => 'Replier la swimlane',
|
||||||
|
'Expand swimlane' => 'Déplier la swimlane',
|
||||||
|
'Add a new filter' => 'Ajouter un nouveau filtre',
|
||||||
|
'Share with all project members' => 'Partager avec tous les membres du projet',
|
||||||
|
'Shared' => 'Partagé',
|
||||||
|
'Owner' => 'Propriétaire',
|
||||||
|
'Unread notifications' => 'Notifications non lus',
|
||||||
|
'My filters' => 'Mes filtres',
|
||||||
|
'Notification methods:' => 'Méthodes de notifications :',
|
||||||
);
|
);
|
||||||
|
|
|
@ -395,8 +395,6 @@ return array(
|
||||||
'Remote' => 'Távoli',
|
'Remote' => 'Távoli',
|
||||||
'Enabled' => 'Engedélyezve',
|
'Enabled' => 'Engedélyezve',
|
||||||
'Disabled' => 'Letiltva',
|
'Disabled' => 'Letiltva',
|
||||||
'Google account linked' => 'Google fiók összekapcsolva',
|
|
||||||
'Github account linked' => 'Github fiók összekapcsolva',
|
|
||||||
'Username:' => 'Felhasználónév:',
|
'Username:' => 'Felhasználónév:',
|
||||||
'Name:' => 'Név:',
|
'Name:' => 'Név:',
|
||||||
'Email:' => 'E-mail:',
|
'Email:' => 'E-mail:',
|
||||||
|
@ -667,75 +665,26 @@ return array(
|
||||||
'Horizontal scrolling' => 'Vízszintes görgetés',
|
'Horizontal scrolling' => 'Vízszintes görgetés',
|
||||||
'Compact/wide view' => 'Kompakt/széles nézet',
|
'Compact/wide view' => 'Kompakt/széles nézet',
|
||||||
'No results match:' => 'Nincs találat:',
|
'No results match:' => 'Nincs találat:',
|
||||||
'Remove hourly rate' => 'Órabér törlése',
|
|
||||||
'Do you really want to remove this hourly rate?' => 'Valóban törölni kívánja az órabért?',
|
|
||||||
'Hourly rates' => 'Órabérek',
|
|
||||||
'Hourly rate' => 'Órabér',
|
|
||||||
'Currency' => 'Pénznem',
|
'Currency' => 'Pénznem',
|
||||||
'Effective date' => 'Hatálybalépés ideje',
|
|
||||||
'Add new rate' => 'Új bér',
|
|
||||||
'Rate removed successfully.' => 'Bér sikeresen törölve.',
|
|
||||||
'Unable to remove this rate.' => 'Bér törlése sikertelen.',
|
|
||||||
'Unable to save the hourly rate.' => 'Órabér mentése sikertelen.',
|
|
||||||
'Hourly rate created successfully.' => 'Órabér sikeresen mentve.',
|
|
||||||
'Start time' => 'Kezdés ideje',
|
|
||||||
'End time' => 'Végzés ideje',
|
|
||||||
'Comment' => 'Megjegyzés',
|
|
||||||
'All day' => 'Egész nap',
|
|
||||||
'Day' => 'Nap',
|
|
||||||
'Manage timetable' => 'Időbeosztás kezelése',
|
|
||||||
'Overtime timetable' => 'Túlóra időbeosztás',
|
|
||||||
'Time off timetable' => 'Szabadság időbeosztás',
|
|
||||||
'Timetable' => 'Időbeosztás',
|
|
||||||
'Work timetable' => 'Munka időbeosztás',
|
|
||||||
'Week timetable' => 'Heti időbeosztás',
|
|
||||||
'Day timetable' => 'Napi időbeosztás',
|
|
||||||
'From' => 'Feladó:',
|
|
||||||
'To' => 'Címzett:',
|
|
||||||
'Time slot created successfully.' => 'Időszelet sikeresen létrehozva.',
|
|
||||||
'Unable to save this time slot.' => 'Időszelet mentése sikertelen.',
|
|
||||||
'Time slot removed successfully.' => 'Időszelet sikeresen törölve.',
|
|
||||||
'Unable to remove this time slot.' => 'Időszelet törlése sikertelen.',
|
|
||||||
'Do you really want to remove this time slot?' => 'Biztos törli ezt az időszeletet?',
|
|
||||||
'Remove time slot' => 'Időszelet törlése',
|
|
||||||
'Add new time slot' => 'Új Időszelet',
|
|
||||||
'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => 'Ez az időbeosztás van használatban ha az "egész nap" jelölőnégyzet be van jelölve a tervezett szabadságnál és túlóránál.',
|
|
||||||
'Files' => 'Fájlok',
|
'Files' => 'Fájlok',
|
||||||
'Images' => 'Képek',
|
'Images' => 'Képek',
|
||||||
'Private project' => 'Privát projekt',
|
'Private project' => 'Privát projekt',
|
||||||
'Amount' => 'Összeg',
|
|
||||||
'AUD - Australian Dollar' => 'AUD - Ausztrál dollár',
|
'AUD - Australian Dollar' => 'AUD - Ausztrál dollár',
|
||||||
'Budget' => 'Költségvetés',
|
|
||||||
'Budget line' => 'Költségvetési tétel',
|
|
||||||
'Budget line removed successfully.' => 'Költségvetési tétel sikeresen törölve.',
|
|
||||||
'Budget lines' => 'Költségvetési tételek',
|
|
||||||
'CAD - Canadian Dollar' => 'CAD - Kanadai dollár',
|
'CAD - Canadian Dollar' => 'CAD - Kanadai dollár',
|
||||||
'CHF - Swiss Francs' => 'CHF - Svájci frank',
|
'CHF - Swiss Francs' => 'CHF - Svájci frank',
|
||||||
'Cost' => 'Költség',
|
|
||||||
'Cost breakdown' => 'Költség visszaszámlálás',
|
|
||||||
'Custom Stylesheet' => 'Egyéni sítluslap',
|
'Custom Stylesheet' => 'Egyéni sítluslap',
|
||||||
'download' => 'letöltés',
|
'download' => 'letöltés',
|
||||||
'Do you really want to remove this budget line?' => 'Biztos törölni akarja ezt a költségvetési tételt?',
|
|
||||||
'EUR - Euro' => 'EUR - Euro',
|
'EUR - Euro' => 'EUR - Euro',
|
||||||
'Expenses' => 'Kiadások',
|
|
||||||
'GBP - British Pound' => 'GBP - Angol font',
|
'GBP - British Pound' => 'GBP - Angol font',
|
||||||
'INR - Indian Rupee' => 'INR - Indiai rúpia',
|
'INR - Indian Rupee' => 'INR - Indiai rúpia',
|
||||||
'JPY - Japanese Yen' => 'JPY - Japán Yen',
|
'JPY - Japanese Yen' => 'JPY - Japán Yen',
|
||||||
'New budget line' => 'Új költségvetési tétel',
|
|
||||||
'NZD - New Zealand Dollar' => 'NZD - Új-Zélandi dollár',
|
'NZD - New Zealand Dollar' => 'NZD - Új-Zélandi dollár',
|
||||||
'Remove a budget line' => 'Költségvetési tétel törlése',
|
|
||||||
'Remove budget line' => 'Költségvetési tétel törlése',
|
|
||||||
'RSD - Serbian dinar' => 'RSD - Szerb dínár',
|
'RSD - Serbian dinar' => 'RSD - Szerb dínár',
|
||||||
'The budget line have been created successfully.' => 'Költségvetési tétel sikeresen létrehozva.',
|
|
||||||
'Unable to create the budget line.' => 'Költségvetési tétel létrehozása sikertelen.',
|
|
||||||
'Unable to remove this budget line.' => 'Költségvetési tétel törlése sikertelen.',
|
|
||||||
'USD - US Dollar' => 'USD - Amerikai ollár',
|
'USD - US Dollar' => 'USD - Amerikai ollár',
|
||||||
'Remaining' => 'Maradék',
|
|
||||||
'Destination column' => 'Cél oszlop',
|
'Destination column' => 'Cél oszlop',
|
||||||
'Move the task to another column when assigned to a user' => 'Feladat másik oszlopba helyezése felhasználóhoz rendélés után',
|
'Move the task to another column when assigned to a user' => 'Feladat másik oszlopba helyezése felhasználóhoz rendélés után',
|
||||||
'Move the task to another column when assignee is cleared' => 'Feladat másik oszlopba helyezése felhasználóhoz rendélés törlésekor',
|
'Move the task to another column when assignee is cleared' => 'Feladat másik oszlopba helyezése felhasználóhoz rendélés törlésekor',
|
||||||
'Source column' => 'Forrás oszlop',
|
'Source column' => 'Forrás oszlop',
|
||||||
// 'Show subtask estimates (forecast of future work)' => '',
|
|
||||||
// 'Transitions' => '',
|
// 'Transitions' => '',
|
||||||
// 'Executer' => '',
|
// 'Executer' => '',
|
||||||
// 'Time spent in the column' => '',
|
// 'Time spent in the column' => '',
|
||||||
|
@ -746,7 +695,6 @@ return array(
|
||||||
// 'Rate' => '',
|
// 'Rate' => '',
|
||||||
// 'Change reference currency' => '',
|
// 'Change reference currency' => '',
|
||||||
// 'Add a new currency rate' => '',
|
// 'Add a new currency rate' => '',
|
||||||
// 'Currency rates are used to calculate project budget.' => '',
|
|
||||||
// 'Reference currency' => '',
|
// 'Reference currency' => '',
|
||||||
// 'The currency rate have been added successfully.' => '',
|
// 'The currency rate have been added successfully.' => '',
|
||||||
// 'Unable to add this currency rate.' => '',
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
@ -878,9 +826,6 @@ return array(
|
||||||
// '%s moved the task #%d to the first swimlane' => '',
|
// '%s moved the task #%d to the first swimlane' => '',
|
||||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||||
// 'Swimlane' => '',
|
// 'Swimlane' => '',
|
||||||
// 'Budget overview' => '',
|
|
||||||
// 'Type' => '',
|
|
||||||
// 'There is not enough data to show something.' => '',
|
|
||||||
// 'Gravatar' => '',
|
// 'Gravatar' => '',
|
||||||
// 'Hipchat' => '',
|
// 'Hipchat' => '',
|
||||||
// 'Slack' => '',
|
// 'Slack' => '',
|
||||||
|
@ -1067,4 +1012,48 @@ return array(
|
||||||
// 'Table of contents' => '',
|
// 'Table of contents' => '',
|
||||||
// 'Gantt' => '',
|
// 'Gantt' => '',
|
||||||
// 'Help with project permissions' => '',
|
// 'Help with project permissions' => '',
|
||||||
|
// 'Author' => '',
|
||||||
|
// 'Version' => '',
|
||||||
|
// 'Plugins' => '',
|
||||||
|
// 'There is no plugin loaded.' => '',
|
||||||
|
// 'Set maximum column height' => '',
|
||||||
|
// 'Remove maximum column height' => '',
|
||||||
|
// 'My notifications' => '',
|
||||||
|
// 'Custom filters' => '',
|
||||||
|
// 'Your custom filter have been created successfully.' => '',
|
||||||
|
// 'Unable to create your custom filter.' => '',
|
||||||
|
// 'Custom filter removed successfully.' => '',
|
||||||
|
// 'Unable to remove this custom filter.' => '',
|
||||||
|
// 'Edit custom filter' => '',
|
||||||
|
// 'Your custom filter have been updated successfully.' => '',
|
||||||
|
// 'Unable to update custom filter.' => '',
|
||||||
|
// 'Web' => '',
|
||||||
|
// 'New attachment on task #%d: %s' => '',
|
||||||
|
// 'New comment on task #%d' => '',
|
||||||
|
// 'Comment updated on task #%d' => '',
|
||||||
|
// 'New subtask on task #%d' => '',
|
||||||
|
// 'Subtask updated on task #%d' => '',
|
||||||
|
// 'New task #%d: %s' => '',
|
||||||
|
// 'Task updated #%d' => '',
|
||||||
|
// 'Task #%d closed' => '',
|
||||||
|
// 'Task #%d opened' => '',
|
||||||
|
// 'Column changed for task #%d' => '',
|
||||||
|
// 'New position for task #%d' => '',
|
||||||
|
// 'Swimlane changed for task #%d' => '',
|
||||||
|
// 'Assignee changed on task #%d' => '',
|
||||||
|
// '%d overdue tasks' => '',
|
||||||
|
// 'Task #%d is overdue' => '',
|
||||||
|
// 'No new notifications.' => '',
|
||||||
|
// 'Mark all as read' => '',
|
||||||
|
// 'Mark as read' => '',
|
||||||
|
// 'Total number of tasks in this column across all swimlanes' => '',
|
||||||
|
// 'Collapse swimlane' => '',
|
||||||
|
// 'Expand swimlane' => '',
|
||||||
|
// 'Add a new filter' => '',
|
||||||
|
// 'Share with all project members' => '',
|
||||||
|
// 'Shared' => '',
|
||||||
|
// 'Owner' => '',
|
||||||
|
// 'Unread notifications' => '',
|
||||||
|
// 'My filters' => '',
|
||||||
|
// 'Notification methods:' => '',
|
||||||
);
|
);
|
||||||
|
|
1059
sources/app/Locale/id_ID/translations.php
Normal file
1059
sources/app/Locale/id_ID/translations.php
Normal file
File diff suppressed because it is too large
Load diff
|
@ -395,8 +395,6 @@ return array(
|
||||||
'Remote' => 'Remoto',
|
'Remote' => 'Remoto',
|
||||||
'Enabled' => 'Abilitato',
|
'Enabled' => 'Abilitato',
|
||||||
'Disabled' => 'Disabilitato',
|
'Disabled' => 'Disabilitato',
|
||||||
'Google account linked' => 'Account Google collegato',
|
|
||||||
'Github account linked' => 'Account Github collegato',
|
|
||||||
// 'Username:' => '',
|
// 'Username:' => '',
|
||||||
'Name:' => 'Nome:',
|
'Name:' => 'Nome:',
|
||||||
// 'Email:' => '',
|
// 'Email:' => '',
|
||||||
|
@ -667,75 +665,26 @@ return array(
|
||||||
'Horizontal scrolling' => 'Scrolling orizzontale',
|
'Horizontal scrolling' => 'Scrolling orizzontale',
|
||||||
'Compact/wide view' => 'Vista compatta/estesa',
|
'Compact/wide view' => 'Vista compatta/estesa',
|
||||||
'No results match:' => 'Nessun risultato trovato:',
|
'No results match:' => 'Nessun risultato trovato:',
|
||||||
'Remove hourly rate' => 'Rimuovi tariffa oraria',
|
|
||||||
'Do you really want to remove this hourly rate?' => 'Vuoi davvero rimuovere questa tariffa oraria?',
|
|
||||||
'Hourly rates' => 'Tariffe orarie',
|
|
||||||
'Hourly rate' => 'Tariffa oraria',
|
|
||||||
'Currency' => 'Valuta',
|
'Currency' => 'Valuta',
|
||||||
'Effective date' => 'Data effettiva',
|
|
||||||
'Add new rate' => 'Aggiungi una nuova tariffa',
|
|
||||||
'Rate removed successfully.' => 'Tariffa rimossa con successo.',
|
|
||||||
'Unable to remove this rate.' => 'Impossibile rimuovere questa tariffa.',
|
|
||||||
'Unable to save the hourly rate.' => 'Impossibile salvare la tariffa oraria.',
|
|
||||||
'Hourly rate created successfully.' => 'Tariffa oraria creata con successo.',
|
|
||||||
'Start time' => 'Data di inizio',
|
|
||||||
'End time' => 'Data di completamento',
|
|
||||||
'Comment' => 'Commento',
|
|
||||||
'All day' => 'Tutto il giorno',
|
|
||||||
'Day' => 'Giorno',
|
|
||||||
'Manage timetable' => 'Gestisci orario',
|
|
||||||
'Overtime timetable' => 'Straordinari',
|
|
||||||
'Time off timetable' => 'Fuori orario',
|
|
||||||
'Timetable' => 'Orario',
|
|
||||||
'Work timetable' => 'Orario di lavoro',
|
|
||||||
'Week timetable' => 'Orario settimanale',
|
|
||||||
'Day timetable' => 'Orario giornaliero',
|
|
||||||
'From' => 'Da',
|
|
||||||
'To' => 'A',
|
|
||||||
'Time slot created successfully.' => 'Fascia oraria creata con successo.',
|
|
||||||
'Unable to save this time slot.' => 'Impossibile creare questa fascia oraria.',
|
|
||||||
'Time slot removed successfully.' => 'Fascia oraria rimossa con successo.',
|
|
||||||
'Unable to remove this time slot.' => 'Impossibile rimuovere questa fascia oraria.',
|
|
||||||
'Do you really want to remove this time slot?' => 'Vuoi davvero rimuovere questa fascia oraria?',
|
|
||||||
'Remove time slot' => 'Rimuovi fascia oraria',
|
|
||||||
'Add new time slot' => 'Aggiungi nuova fascia oraria',
|
|
||||||
'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => 'Questo orario è utilizzato quando la casella "tutto il giorno" è selezionata per i fuori orari e per gli straordinari',
|
|
||||||
// 'Files' => '',
|
// 'Files' => '',
|
||||||
'Images' => 'Immagini',
|
'Images' => 'Immagini',
|
||||||
'Private project' => 'Progetto privato',
|
'Private project' => 'Progetto privato',
|
||||||
'Amount' => 'Totale',
|
|
||||||
'AUD - Australian Dollar' => 'AUD - Dollari Australiani',
|
'AUD - Australian Dollar' => 'AUD - Dollari Australiani',
|
||||||
'Budget' => 'Bilancio',
|
|
||||||
'Budget line' => 'Limite di bilancio',
|
|
||||||
'Budget line removed successfully.' => 'Limite al bilancio rimosso con successo.',
|
|
||||||
'Budget lines' => 'Limiti al bilancio',
|
|
||||||
'CAD - Canadian Dollar' => 'CAD - Dollari Canadesi',
|
'CAD - Canadian Dollar' => 'CAD - Dollari Canadesi',
|
||||||
'CHF - Swiss Francs' => 'CHF - Franchi Svizzeri',
|
'CHF - Swiss Francs' => 'CHF - Franchi Svizzeri',
|
||||||
'Cost' => 'Costi',
|
|
||||||
'Cost breakdown' => 'Abbattimento dei costi',
|
|
||||||
'Custom Stylesheet' => 'CSS personalizzato',
|
'Custom Stylesheet' => 'CSS personalizzato',
|
||||||
// 'download' => '',
|
// 'download' => '',
|
||||||
'Do you really want to remove this budget line?' => 'Vuoi davvero rimuovere questo limite al bilancio?',
|
|
||||||
// 'EUR - Euro' => '',
|
// 'EUR - Euro' => '',
|
||||||
'Expenses' => 'Spese',
|
|
||||||
'GBP - British Pound' => 'GBP - Pound Inglesi',
|
'GBP - British Pound' => 'GBP - Pound Inglesi',
|
||||||
'INR - Indian Rupee' => 'INR - Rupie Indiani',
|
'INR - Indian Rupee' => 'INR - Rupie Indiani',
|
||||||
'JPY - Japanese Yen' => 'JPY - Yen Giapponesi',
|
'JPY - Japanese Yen' => 'JPY - Yen Giapponesi',
|
||||||
'New budget line' => 'Nuovo limite al bilancio',
|
|
||||||
'NZD - New Zealand Dollar' => 'NZD - Dollari della Nuova Zelanda',
|
'NZD - New Zealand Dollar' => 'NZD - Dollari della Nuova Zelanda',
|
||||||
'Remove a budget line' => 'Rimuovi un limite al bilancio',
|
|
||||||
'Remove budget line' => 'Rimuovi limite di bilancio',
|
|
||||||
'RSD - Serbian dinar' => 'RSD - Dinar Serbi',
|
'RSD - Serbian dinar' => 'RSD - Dinar Serbi',
|
||||||
'The budget line have been created successfully.' => 'Il limite al bilancio è stato creato correttamente',
|
|
||||||
'Unable to create the budget line.' => 'Impossibile creare il limite al bilancio',
|
|
||||||
'Unable to remove this budget line.' => 'Impossibile rimuovere questo limite al bilancio.',
|
|
||||||
'USD - US Dollar' => 'USD - Dollari Americani',
|
'USD - US Dollar' => 'USD - Dollari Americani',
|
||||||
'Remaining' => 'Restanti',
|
|
||||||
'Destination column' => 'Colonna destinazione',
|
'Destination column' => 'Colonna destinazione',
|
||||||
'Move the task to another column when assigned to a user' => 'Sposta il compito in un\'altra colonna quando viene assegnato ad un utente',
|
'Move the task to another column when assigned to a user' => 'Sposta il compito in un\'altra colonna quando viene assegnato ad un utente',
|
||||||
'Move the task to another column when assignee is cleared' => 'Sposta il compito in un\'altra colonna quando l\'assegnatario cancellato',
|
'Move the task to another column when assignee is cleared' => 'Sposta il compito in un\'altra colonna quando l\'assegnatario cancellato',
|
||||||
'Source column' => 'Colonna sorgente',
|
'Source column' => 'Colonna sorgente',
|
||||||
// 'Show subtask estimates (forecast of future work)' => '',
|
|
||||||
'Transitions' => 'Transizioni',
|
'Transitions' => 'Transizioni',
|
||||||
'Executer' => 'Esecutore',
|
'Executer' => 'Esecutore',
|
||||||
'Time spent in the column' => 'Tempo trascorso nella colonna',
|
'Time spent in the column' => 'Tempo trascorso nella colonna',
|
||||||
|
@ -746,7 +695,6 @@ return array(
|
||||||
'Rate' => 'Cambio',
|
'Rate' => 'Cambio',
|
||||||
'Change reference currency' => 'Cambia la valuta di riferimento',
|
'Change reference currency' => 'Cambia la valuta di riferimento',
|
||||||
'Add a new currency rate' => 'Aggiungi un nuovo tasso di cambio',
|
'Add a new currency rate' => 'Aggiungi un nuovo tasso di cambio',
|
||||||
'Currency rates are used to calculate project budget.' => 'I tassi di cambio sono utilizzati per calcolare i bilanci dei progetti',
|
|
||||||
'Reference currency' => 'Valuta di riferimento',
|
'Reference currency' => 'Valuta di riferimento',
|
||||||
'The currency rate have been added successfully.' => 'Il tasso di cambio è stato aggiunto con successo.',
|
'The currency rate have been added successfully.' => 'Il tasso di cambio è stato aggiunto con successo.',
|
||||||
'Unable to add this currency rate.' => 'Impossibile aggiungere questo tasso di cambio.',
|
'Unable to add this currency rate.' => 'Impossibile aggiungere questo tasso di cambio.',
|
||||||
|
@ -878,9 +826,6 @@ return array(
|
||||||
// '%s moved the task #%d to the first swimlane' => '',
|
// '%s moved the task #%d to the first swimlane' => '',
|
||||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||||
// 'Swimlane' => '',
|
// 'Swimlane' => '',
|
||||||
// 'Budget overview' => '',
|
|
||||||
// 'Type' => '',
|
|
||||||
// 'There is not enough data to show something.' => '',
|
|
||||||
// 'Gravatar' => '',
|
// 'Gravatar' => '',
|
||||||
// 'Hipchat' => '',
|
// 'Hipchat' => '',
|
||||||
// 'Slack' => '',
|
// 'Slack' => '',
|
||||||
|
@ -1067,4 +1012,48 @@ return array(
|
||||||
// 'Table of contents' => '',
|
// 'Table of contents' => '',
|
||||||
// 'Gantt' => '',
|
// 'Gantt' => '',
|
||||||
// 'Help with project permissions' => '',
|
// 'Help with project permissions' => '',
|
||||||
|
// 'Author' => '',
|
||||||
|
// 'Version' => '',
|
||||||
|
// 'Plugins' => '',
|
||||||
|
// 'There is no plugin loaded.' => '',
|
||||||
|
// 'Set maximum column height' => '',
|
||||||
|
// 'Remove maximum column height' => '',
|
||||||
|
// 'My notifications' => '',
|
||||||
|
// 'Custom filters' => '',
|
||||||
|
// 'Your custom filter have been created successfully.' => '',
|
||||||
|
// 'Unable to create your custom filter.' => '',
|
||||||
|
// 'Custom filter removed successfully.' => '',
|
||||||
|
// 'Unable to remove this custom filter.' => '',
|
||||||
|
// 'Edit custom filter' => '',
|
||||||
|
// 'Your custom filter have been updated successfully.' => '',
|
||||||
|
// 'Unable to update custom filter.' => '',
|
||||||
|
// 'Web' => '',
|
||||||
|
// 'New attachment on task #%d: %s' => '',
|
||||||
|
// 'New comment on task #%d' => '',
|
||||||
|
// 'Comment updated on task #%d' => '',
|
||||||
|
// 'New subtask on task #%d' => '',
|
||||||
|
// 'Subtask updated on task #%d' => '',
|
||||||
|
// 'New task #%d: %s' => '',
|
||||||
|
// 'Task updated #%d' => '',
|
||||||
|
// 'Task #%d closed' => '',
|
||||||
|
// 'Task #%d opened' => '',
|
||||||
|
// 'Column changed for task #%d' => '',
|
||||||
|
// 'New position for task #%d' => '',
|
||||||
|
// 'Swimlane changed for task #%d' => '',
|
||||||
|
// 'Assignee changed on task #%d' => '',
|
||||||
|
// '%d overdue tasks' => '',
|
||||||
|
// 'Task #%d is overdue' => '',
|
||||||
|
// 'No new notifications.' => '',
|
||||||
|
// 'Mark all as read' => '',
|
||||||
|
// 'Mark as read' => '',
|
||||||
|
// 'Total number of tasks in this column across all swimlanes' => '',
|
||||||
|
// 'Collapse swimlane' => '',
|
||||||
|
// 'Expand swimlane' => '',
|
||||||
|
// 'Add a new filter' => '',
|
||||||
|
// 'Share with all project members' => '',
|
||||||
|
// 'Shared' => '',
|
||||||
|
// 'Owner' => '',
|
||||||
|
// 'Unread notifications' => '',
|
||||||
|
// 'My filters' => '',
|
||||||
|
// 'Notification methods:' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -395,8 +395,6 @@ return array(
|
||||||
'Remote' => 'リモート',
|
'Remote' => 'リモート',
|
||||||
'Enabled' => '有効',
|
'Enabled' => '有効',
|
||||||
'Disabled' => '無効',
|
'Disabled' => '無効',
|
||||||
'Google account linked' => 'Google アカウントがリンク',
|
|
||||||
'Github account linked' => 'Github のアカウントがリンク',
|
|
||||||
'Username:' => 'ユーザ名:',
|
'Username:' => 'ユーザ名:',
|
||||||
'Name:' => '名前:',
|
'Name:' => '名前:',
|
||||||
'Email:' => 'Email:',
|
'Email:' => 'Email:',
|
||||||
|
@ -667,75 +665,26 @@ return array(
|
||||||
'Horizontal scrolling' => '縦スクロール',
|
'Horizontal scrolling' => '縦スクロール',
|
||||||
'Compact/wide view' => 'コンパクト/ワイドビュー',
|
'Compact/wide view' => 'コンパクト/ワイドビュー',
|
||||||
'No results match:' => '結果が一致しませんでした',
|
'No results match:' => '結果が一致しませんでした',
|
||||||
'Remove hourly rate' => '毎時レートを削除',
|
|
||||||
'Do you really want to remove this hourly rate?' => '毎時レートを削除しますか?',
|
|
||||||
'Hourly rates' => '毎時レート',
|
|
||||||
'Hourly rate' => '毎時レート',
|
|
||||||
'Currency' => '通貨',
|
'Currency' => '通貨',
|
||||||
'Effective date' => '有効期限',
|
|
||||||
'Add new rate' => '新しいレート',
|
|
||||||
'Rate removed successfully.' => 'レートの削除に成功しました。',
|
|
||||||
'Unable to remove this rate.' => 'レートを削除できませんでした。',
|
|
||||||
'Unable to save the hourly rate.' => '時間毎のレートを保存できませんでした。',
|
|
||||||
'Hourly rate created successfully.' => '時間毎のレートを作成しました。',
|
|
||||||
'Start time' => '開始時間',
|
|
||||||
'End time' => '終了時間',
|
|
||||||
'Comment' => 'コメント',
|
|
||||||
'All day' => '終日',
|
|
||||||
'Day' => '日',
|
|
||||||
'Manage timetable' => 'タイムテーブルの管理',
|
|
||||||
'Overtime timetable' => '残業タイムテーブル',
|
|
||||||
'Time off timetable' => '休暇タイムテーブル',
|
|
||||||
'Timetable' => 'タイムテーブル',
|
|
||||||
'Work timetable' => 'ワークタイムテーブル',
|
|
||||||
'Week timetable' => '週次タイムテーブル',
|
|
||||||
'Day timetable' => '日時タイムテーブル',
|
|
||||||
'From' => 'ここから',
|
|
||||||
'To' => 'ここまで',
|
|
||||||
// 'Time slot created successfully.' => '',
|
|
||||||
// 'Unable to save this time slot.' => '',
|
|
||||||
// 'Time slot removed successfully.' => '',
|
|
||||||
// 'Unable to remove this time slot.' => '',
|
|
||||||
// 'Do you really want to remove this time slot?' => '',
|
|
||||||
'Remove time slot' => 'タイムスロットの削除',
|
|
||||||
'Add new time slot' => 'タイムラインの追加',
|
|
||||||
'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => 'このタイムテーブルは、残業や休暇で全日がチェックされた場合に用いられます。',
|
|
||||||
'Files' => 'ファイル',
|
'Files' => 'ファイル',
|
||||||
'Images' => '画像',
|
'Images' => '画像',
|
||||||
'Private project' => 'プライベートプロジェクト',
|
'Private project' => 'プライベートプロジェクト',
|
||||||
'Amount' => '数量',
|
|
||||||
'AUD - Australian Dollar' => 'AUD - 豪ドル',
|
'AUD - Australian Dollar' => 'AUD - 豪ドル',
|
||||||
'Budget' => '予算',
|
|
||||||
'Budget line' => '予算ライン',
|
|
||||||
'Budget line removed successfully.' => '予算ラインを削除しました.',
|
|
||||||
'Budget lines' => '予算ライン',
|
|
||||||
'CAD - Canadian Dollar' => 'CAD - 加ドル',
|
'CAD - Canadian Dollar' => 'CAD - 加ドル',
|
||||||
'CHF - Swiss Francs' => 'CHF - スイスフラン',
|
'CHF - Swiss Francs' => 'CHF - スイスフラン',
|
||||||
'Cost' => 'コスト',
|
|
||||||
'Cost breakdown' => 'コストブレークダウン',
|
|
||||||
'Custom Stylesheet' => 'カスタムスタイルシート',
|
'Custom Stylesheet' => 'カスタムスタイルシート',
|
||||||
'download' => 'ダウンロード',
|
'download' => 'ダウンロード',
|
||||||
'Do you really want to remove this budget line?' => 'この予算ラインを本当に削除しますか?',
|
|
||||||
'EUR - Euro' => 'EUR - ユーロ',
|
'EUR - Euro' => 'EUR - ユーロ',
|
||||||
'Expenses' => '支出',
|
|
||||||
'GBP - British Pound' => 'GBP - 独ポンド',
|
'GBP - British Pound' => 'GBP - 独ポンド',
|
||||||
'INR - Indian Rupee' => 'INR - 伊ルピー',
|
'INR - Indian Rupee' => 'INR - 伊ルピー',
|
||||||
'JPY - Japanese Yen' => 'JPY - 日本円',
|
'JPY - Japanese Yen' => 'JPY - 日本円',
|
||||||
'New budget line' => '新しい予算ライン',
|
|
||||||
'NZD - New Zealand Dollar' => 'NZD - NZ ドル',
|
'NZD - New Zealand Dollar' => 'NZD - NZ ドル',
|
||||||
'Remove a budget line' => '予算ラインの削除',
|
|
||||||
'Remove budget line' => '予算ラインの削除',
|
|
||||||
'RSD - Serbian dinar' => 'RSD - セルビアデナール',
|
'RSD - Serbian dinar' => 'RSD - セルビアデナール',
|
||||||
'The budget line have been created successfully.' => '予算ラインを作成しました',
|
|
||||||
'Unable to create the budget line.' => '予算ラインを作成できませんでした。',
|
|
||||||
'Unable to remove this budget line.' => '予算ラインを削除できませんでした。',
|
|
||||||
'USD - US Dollar' => 'USD - 米ドル',
|
'USD - US Dollar' => 'USD - 米ドル',
|
||||||
'Remaining' => '残り',
|
|
||||||
'Destination column' => '移動先のカラム',
|
'Destination column' => '移動先のカラム',
|
||||||
'Move the task to another column when assigned to a user' => 'ユーザの割り当てをしたらタスクを他のカラムに移動',
|
'Move the task to another column when assigned to a user' => 'ユーザの割り当てをしたらタスクを他のカラムに移動',
|
||||||
'Move the task to another column when assignee is cleared' => 'ユーザの割り当てがなくなったらタスクを他のカラムに移動',
|
'Move the task to another column when assignee is cleared' => 'ユーザの割り当てがなくなったらタスクを他のカラムに移動',
|
||||||
'Source column' => '移動元のカラム',
|
'Source column' => '移動元のカラム',
|
||||||
// 'Show subtask estimates (forecast of future work)' => '',
|
|
||||||
'Transitions' => '履歴',
|
'Transitions' => '履歴',
|
||||||
'Executer' => '実行者',
|
'Executer' => '実行者',
|
||||||
'Time spent in the column' => 'カラムでの時間消費',
|
'Time spent in the column' => 'カラムでの時間消費',
|
||||||
|
@ -746,7 +695,6 @@ return array(
|
||||||
'Rate' => 'レート',
|
'Rate' => 'レート',
|
||||||
'Change reference currency' => '現在の基軸通貨',
|
'Change reference currency' => '現在の基軸通貨',
|
||||||
'Add a new currency rate' => '新しい通貨レートを追加',
|
'Add a new currency rate' => '新しい通貨レートを追加',
|
||||||
'Currency rates are used to calculate project budget.' => '通貨レートはプロジェクト予算の算出に利用されます。',
|
|
||||||
'Reference currency' => '基軸通貨',
|
'Reference currency' => '基軸通貨',
|
||||||
// 'The currency rate have been added successfully.' => '',
|
// 'The currency rate have been added successfully.' => '',
|
||||||
'Unable to add this currency rate.' => 'この通貨レートを追加できません。',
|
'Unable to add this currency rate.' => 'この通貨レートを追加できません。',
|
||||||
|
@ -878,9 +826,6 @@ return array(
|
||||||
// '%s moved the task #%d to the first swimlane' => '',
|
// '%s moved the task #%d to the first swimlane' => '',
|
||||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||||
// 'Swimlane' => '',
|
// 'Swimlane' => '',
|
||||||
// 'Budget overview' => '',
|
|
||||||
// 'Type' => '',
|
|
||||||
// 'There is not enough data to show something.' => '',
|
|
||||||
// 'Gravatar' => '',
|
// 'Gravatar' => '',
|
||||||
// 'Hipchat' => '',
|
// 'Hipchat' => '',
|
||||||
// 'Slack' => '',
|
// 'Slack' => '',
|
||||||
|
@ -1067,4 +1012,48 @@ return array(
|
||||||
// 'Table of contents' => '',
|
// 'Table of contents' => '',
|
||||||
// 'Gantt' => '',
|
// 'Gantt' => '',
|
||||||
// 'Help with project permissions' => '',
|
// 'Help with project permissions' => '',
|
||||||
|
// 'Author' => '',
|
||||||
|
// 'Version' => '',
|
||||||
|
// 'Plugins' => '',
|
||||||
|
// 'There is no plugin loaded.' => '',
|
||||||
|
// 'Set maximum column height' => '',
|
||||||
|
// 'Remove maximum column height' => '',
|
||||||
|
// 'My notifications' => '',
|
||||||
|
// 'Custom filters' => '',
|
||||||
|
// 'Your custom filter have been created successfully.' => '',
|
||||||
|
// 'Unable to create your custom filter.' => '',
|
||||||
|
// 'Custom filter removed successfully.' => '',
|
||||||
|
// 'Unable to remove this custom filter.' => '',
|
||||||
|
// 'Edit custom filter' => '',
|
||||||
|
// 'Your custom filter have been updated successfully.' => '',
|
||||||
|
// 'Unable to update custom filter.' => '',
|
||||||
|
// 'Web' => '',
|
||||||
|
// 'New attachment on task #%d: %s' => '',
|
||||||
|
// 'New comment on task #%d' => '',
|
||||||
|
// 'Comment updated on task #%d' => '',
|
||||||
|
// 'New subtask on task #%d' => '',
|
||||||
|
// 'Subtask updated on task #%d' => '',
|
||||||
|
// 'New task #%d: %s' => '',
|
||||||
|
// 'Task updated #%d' => '',
|
||||||
|
// 'Task #%d closed' => '',
|
||||||
|
// 'Task #%d opened' => '',
|
||||||
|
// 'Column changed for task #%d' => '',
|
||||||
|
// 'New position for task #%d' => '',
|
||||||
|
// 'Swimlane changed for task #%d' => '',
|
||||||
|
// 'Assignee changed on task #%d' => '',
|
||||||
|
// '%d overdue tasks' => '',
|
||||||
|
// 'Task #%d is overdue' => '',
|
||||||
|
// 'No new notifications.' => '',
|
||||||
|
// 'Mark all as read' => '',
|
||||||
|
// 'Mark as read' => '',
|
||||||
|
// 'Total number of tasks in this column across all swimlanes' => '',
|
||||||
|
// 'Collapse swimlane' => '',
|
||||||
|
// 'Expand swimlane' => '',
|
||||||
|
// 'Add a new filter' => '',
|
||||||
|
// 'Share with all project members' => '',
|
||||||
|
// 'Shared' => '',
|
||||||
|
// 'Owner' => '',
|
||||||
|
// 'Unread notifications' => '',
|
||||||
|
// 'My filters' => '',
|
||||||
|
// 'Notification methods:' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
// 'number.decimals_separator' => '',
|
'number.decimals_separator' => ',',
|
||||||
// 'number.thousands_separator' => '',
|
'number.thousands_separator' => '.',
|
||||||
'None' => 'Ingen',
|
'None' => 'Ingen',
|
||||||
'edit' => 'rediger',
|
'edit' => 'rediger',
|
||||||
'Edit' => 'Rediger',
|
'Edit' => 'Rediger',
|
||||||
|
@ -79,7 +79,7 @@ return array(
|
||||||
'Assigned to %s' => 'Tildelt: %s',
|
'Assigned to %s' => 'Tildelt: %s',
|
||||||
'Remove a column' => 'Fjern en kolonne',
|
'Remove a column' => 'Fjern en kolonne',
|
||||||
'Remove a column from a board' => 'Fjern en kolonne fra et board',
|
'Remove a column from a board' => 'Fjern en kolonne fra et board',
|
||||||
'Unable to remove this column.' => 'Ikke mulig fjerne denne kolonnen',
|
'Unable to remove this column.' => 'Ikke mulig ø fjerne denne kolonnen',
|
||||||
'Do you really want to remove this column: "%s"?' => 'Vil du fjerne denne kolonnen: "%s"?',
|
'Do you really want to remove this column: "%s"?' => 'Vil du fjerne denne kolonnen: "%s"?',
|
||||||
'This action will REMOVE ALL TASKS associated to this column!' => 'Denne handlingen vil SLETTE ALLE OPPGAVER tilknyttet denne kolonnen',
|
'This action will REMOVE ALL TASKS associated to this column!' => 'Denne handlingen vil SLETTE ALLE OPPGAVER tilknyttet denne kolonnen',
|
||||||
'Settings' => 'Innstillinger',
|
'Settings' => 'Innstillinger',
|
||||||
|
@ -100,7 +100,7 @@ return array(
|
||||||
'Create another task' => 'Opprett en annen oppgave',
|
'Create another task' => 'Opprett en annen oppgave',
|
||||||
'New task' => 'Ny oppgave',
|
'New task' => 'Ny oppgave',
|
||||||
'Open a task' => 'Åpne en oppgave',
|
'Open a task' => 'Åpne en oppgave',
|
||||||
'Do you really want to open this task: "%s"?' => 'Vil du åpe denne oppgaven: "%s"?',
|
'Do you really want to open this task: "%s"?' => 'Vil du åpne denne oppgaven: "%s"?',
|
||||||
'Back to the board' => 'Tilbake til prosjektsiden',
|
'Back to the board' => 'Tilbake til prosjektsiden',
|
||||||
'Created on %B %e, %Y at %k:%M %p' => 'Opprettet %d.%m.%Y - %H:%M',
|
'Created on %B %e, %Y at %k:%M %p' => 'Opprettet %d.%m.%Y - %H:%M',
|
||||||
'There is nobody assigned' => 'Mangler tildeling',
|
'There is nobody assigned' => 'Mangler tildeling',
|
||||||
|
@ -121,7 +121,7 @@ return array(
|
||||||
'Passwords don\'t match' => 'Passordene stemmer ikke overens',
|
'Passwords don\'t match' => 'Passordene stemmer ikke overens',
|
||||||
'The confirmation is required' => 'Bekreftelse er nødvendig',
|
'The confirmation is required' => 'Bekreftelse er nødvendig',
|
||||||
'The project is required' => 'Prosjektet er påkrevet',
|
'The project is required' => 'Prosjektet er påkrevet',
|
||||||
'The id is required' => 'Id\'en er påkrevd',
|
'The id is required' => 'Id\'en er pøøkrevet',
|
||||||
'The project id is required' => 'Prosjektet-id er påkrevet',
|
'The project id is required' => 'Prosjektet-id er påkrevet',
|
||||||
'The project name is required' => 'Prosjektnavn er påkrevet',
|
'The project name is required' => 'Prosjektnavn er påkrevet',
|
||||||
'This project must be unique' => 'Prosjektnavnet skal være unikt',
|
'This project must be unique' => 'Prosjektnavnet skal være unikt',
|
||||||
|
@ -149,7 +149,7 @@ return array(
|
||||||
'Task created successfully.' => 'Oppgaven er opprettet.',
|
'Task created successfully.' => 'Oppgaven er opprettet.',
|
||||||
'User created successfully.' => 'Brukeren er opprettet.',
|
'User created successfully.' => 'Brukeren er opprettet.',
|
||||||
'Unable to create your user.' => 'Brukeren kunne ikke opprettes.',
|
'Unable to create your user.' => 'Brukeren kunne ikke opprettes.',
|
||||||
'User updated successfully.' => 'Brukeren er opdateret',
|
'User updated successfully.' => 'Brukeren er oppdatert',
|
||||||
'Unable to update your user.' => 'Din bruker kunne ikke oppdateres.',
|
'Unable to update your user.' => 'Din bruker kunne ikke oppdateres.',
|
||||||
'User removed successfully.' => 'Brukeren er fjernet.',
|
'User removed successfully.' => 'Brukeren er fjernet.',
|
||||||
'Unable to remove this user.' => 'Brukeren kunne ikke slettes.',
|
'Unable to remove this user.' => 'Brukeren kunne ikke slettes.',
|
||||||
|
@ -175,10 +175,10 @@ return array(
|
||||||
'Page not found' => 'Siden er ikke funnet',
|
'Page not found' => 'Siden er ikke funnet',
|
||||||
'Complexity' => 'Kompleksitet',
|
'Complexity' => 'Kompleksitet',
|
||||||
'Task limit' => 'Oppgave begrensning',
|
'Task limit' => 'Oppgave begrensning',
|
||||||
// 'Task count' => '',
|
'Task count' => 'Antall oppgaver',
|
||||||
'Edit project access list' => 'Endre tillatelser for prosjektet',
|
'Edit project access list' => 'Endre tillatelser for prosjektet',
|
||||||
'Allow this user' => 'Tillat denne brukeren',
|
'Allow this user' => 'Tillat denne brukeren',
|
||||||
'Don\'t forget that administrators have access to everything.' => 'Hust at administratorer har tilgang til alt.',
|
'Don\'t forget that administrators have access to everything.' => 'Husk at administratorer har tilgang til alt.',
|
||||||
'Revoke' => 'Fjern',
|
'Revoke' => 'Fjern',
|
||||||
'List of authorized users' => 'Liste over autoriserte brukere',
|
'List of authorized users' => 'Liste over autoriserte brukere',
|
||||||
'User' => 'Bruker',
|
'User' => 'Bruker',
|
||||||
|
@ -205,16 +205,16 @@ return array(
|
||||||
'Automatic actions for the project "%s"' => 'Automatiske handlinger for prosjektet "%s"',
|
'Automatic actions for the project "%s"' => 'Automatiske handlinger for prosjektet "%s"',
|
||||||
'Defined actions' => 'Definerte handlinger',
|
'Defined actions' => 'Definerte handlinger',
|
||||||
'Add an action' => 'Legg til en handling',
|
'Add an action' => 'Legg til en handling',
|
||||||
'Event name' => 'Begivenhet',
|
'Event name' => 'Hendelsehet',
|
||||||
'Action name' => 'Handling',
|
'Action name' => 'Handling',
|
||||||
'Action parameters' => 'Handlingsparametre',
|
'Action parameters' => 'Handlingsparametre',
|
||||||
'Action' => 'Handling',
|
'Action' => 'Handling',
|
||||||
'Event' => 'Begivenhet',
|
'Event' => 'Hendelse',
|
||||||
'When the selected event occurs execute the corresponding action.' => 'Når den valgtebegivenheten oppstår, utføre tilsvarende handlin.',
|
'When the selected event occurs execute the corresponding action.' => 'Når den valgte hendelsen oppstår, utfør tilsvarende handling.',
|
||||||
'Next step' => 'Neste',
|
'Next step' => 'Neste',
|
||||||
'Define action parameters' => 'Definer handlingsparametre',
|
'Define action parameters' => 'Definer handlingsparametre',
|
||||||
'Save this action' => 'Lagre handlingen',
|
'Save this action' => 'Lagre handlingen',
|
||||||
'Do you really want to remove this action: "%s"?' => 'Vil du virkelig slette denne handlingen: "%s"?',
|
'Do you really want to remove this action: "%s"?' => 'Vil du slette denne handlingen: "%s"?',
|
||||||
'Remove an automatic action' => 'Fjern en automatisk handling',
|
'Remove an automatic action' => 'Fjern en automatisk handling',
|
||||||
'Assign the task to a specific user' => 'Tildel oppgaven til en bestemt bruker',
|
'Assign the task to a specific user' => 'Tildel oppgaven til en bestemt bruker',
|
||||||
'Assign the task to the person who does the action' => 'Tildel oppgaven til den person, som utfører handlingen',
|
'Assign the task to the person who does the action' => 'Tildel oppgaven til den person, som utfører handlingen',
|
||||||
|
@ -236,13 +236,13 @@ return array(
|
||||||
'Remove a comment' => 'Fjern en kommentar',
|
'Remove a comment' => 'Fjern en kommentar',
|
||||||
'Comment removed successfully.' => 'Kommentaren ble fjernet.',
|
'Comment removed successfully.' => 'Kommentaren ble fjernet.',
|
||||||
'Unable to remove this comment.' => 'Kommentaren kunne ikke fjernes.',
|
'Unable to remove this comment.' => 'Kommentaren kunne ikke fjernes.',
|
||||||
'Do you really want to remove this comment?' => 'Vil du virkelig fjerne denne kommentaren?',
|
'Do you really want to remove this comment?' => 'Vil du fjerne denne kommentaren?',
|
||||||
'Only administrators or the creator of the comment can access to this page.' => 'Kun administrator eller brukeren, som har oprettet kommentaren har adgang til denne siden.',
|
'Only administrators or the creator of the comment can access to this page.' => 'Kun administrator eller brukeren, som har oprettet kommentaren har adgang til denne siden.',
|
||||||
'Current password for the user "%s"' => 'Aktivt passord for brukeren "%s"',
|
'Current password for the user "%s"' => 'Aktivt passord for brukeren "%s"',
|
||||||
'The current password is required' => 'Passord er påkrevet',
|
'The current password is required' => 'Passord er påkrevet',
|
||||||
'Wrong password' => 'Feil passord',
|
'Wrong password' => 'Feil passord',
|
||||||
'Unknown' => 'Ukjent',
|
'Unknown' => 'Ukjent',
|
||||||
'Last logins' => 'Siste login',
|
'Last logins' => 'Siste innlogging',
|
||||||
'Login date' => 'Login dato',
|
'Login date' => 'Login dato',
|
||||||
'Authentication method' => 'Godkjenningsmetode',
|
'Authentication method' => 'Godkjenningsmetode',
|
||||||
'IP address' => 'IP Adresse',
|
'IP address' => 'IP Adresse',
|
||||||
|
@ -275,7 +275,7 @@ return array(
|
||||||
'Task removed successfully.' => 'Oppgaven er fjernet.',
|
'Task removed successfully.' => 'Oppgaven er fjernet.',
|
||||||
'Unable to remove this task.' => 'Oppgaven kunne ikke fjernes.',
|
'Unable to remove this task.' => 'Oppgaven kunne ikke fjernes.',
|
||||||
'Remove a task' => 'Fjern en oppgave',
|
'Remove a task' => 'Fjern en oppgave',
|
||||||
'Do you really want to remove this task: "%s"?' => 'Vil du virkelig fjerne denne opgave: "%s"?',
|
'Do you really want to remove this task: "%s"?' => 'Vil du fjerne denne oppgaven: "%s"?',
|
||||||
'Assign automatically a color based on a category' => 'Tildel automatisk en farge baseret for en kategori',
|
'Assign automatically a color based on a category' => 'Tildel automatisk en farge baseret for en kategori',
|
||||||
'Assign automatically a category based on a color' => 'Tildel automatisk en kategori basert på en farve',
|
'Assign automatically a category based on a color' => 'Tildel automatisk en kategori basert på en farve',
|
||||||
'Task creation or modification' => 'Oppgaveopprettelse eller endring',
|
'Task creation or modification' => 'Oppgaveopprettelse eller endring',
|
||||||
|
@ -293,7 +293,7 @@ return array(
|
||||||
'Category modification for the project "%s"' => 'Endring av kategori for prosjektet "%s"',
|
'Category modification for the project "%s"' => 'Endring av kategori for prosjektet "%s"',
|
||||||
'Category Name' => 'Kategorinavn',
|
'Category Name' => 'Kategorinavn',
|
||||||
'Add a new category' => 'Legg til ny kategori',
|
'Add a new category' => 'Legg til ny kategori',
|
||||||
'Do you really want to remove this category: "%s"?' => 'Vil du virkelig fjerne kategorien: "%s"?',
|
'Do you really want to remove this category: "%s"?' => 'Vil du fjerne kategorien: "%s"?',
|
||||||
'All categories' => 'Alle kategorier',
|
'All categories' => 'Alle kategorier',
|
||||||
'No category' => 'Ingen kategori',
|
'No category' => 'Ingen kategori',
|
||||||
'The name is required' => 'Navnet er påkrevet',
|
'The name is required' => 'Navnet er påkrevet',
|
||||||
|
@ -301,9 +301,9 @@ return array(
|
||||||
'Unable to remove this file.' => 'Filen kunne ikke fjernes.',
|
'Unable to remove this file.' => 'Filen kunne ikke fjernes.',
|
||||||
'File removed successfully.' => 'Filen er fjernet.',
|
'File removed successfully.' => 'Filen er fjernet.',
|
||||||
'Attach a document' => 'Legg til et dokument',
|
'Attach a document' => 'Legg til et dokument',
|
||||||
'Do you really want to remove this file: "%s"?' => 'Vil du virkelig fjerne filen: "%s"?',
|
'Do you really want to remove this file: "%s"?' => 'Vil du fjerne filen: "%s"?',
|
||||||
'open' => 'åpen',
|
'open' => 'øpen',
|
||||||
'Attachments' => 'Vedleggr',
|
'Attachments' => 'Vedlegg',
|
||||||
'Edit the task' => 'Rediger oppgaven',
|
'Edit the task' => 'Rediger oppgaven',
|
||||||
'Edit the description' => 'Rediger beskrivelsen',
|
'Edit the description' => 'Rediger beskrivelsen',
|
||||||
'Add a comment' => 'Legg til en kommentar',
|
'Add a comment' => 'Legg til en kommentar',
|
||||||
|
@ -312,7 +312,7 @@ return array(
|
||||||
'Time tracking' => 'Tidsregistrering',
|
'Time tracking' => 'Tidsregistrering',
|
||||||
'Estimate:' => 'Estimat:',
|
'Estimate:' => 'Estimat:',
|
||||||
'Spent:' => 'Brukt:',
|
'Spent:' => 'Brukt:',
|
||||||
'Do you really want to remove this sub-task?' => 'Vil du virkelig fjerne denne deloppgaven?',
|
'Do you really want to remove this sub-task?' => 'Vil du fjerne denne deloppgaven?',
|
||||||
'Remaining:' => 'Gjenværende:',
|
'Remaining:' => 'Gjenværende:',
|
||||||
'hours' => 'timer',
|
'hours' => 'timer',
|
||||||
'spent' => 'brukt',
|
'spent' => 'brukt',
|
||||||
|
@ -354,7 +354,7 @@ return array(
|
||||||
'Project cloned successfully.' => 'Prosjektet er kopiert.',
|
'Project cloned successfully.' => 'Prosjektet er kopiert.',
|
||||||
'Unable to clone this project.' => 'Prosjektet kunne ikke kopieres',
|
'Unable to clone this project.' => 'Prosjektet kunne ikke kopieres',
|
||||||
'Email notifications' => 'Epostvarslinger',
|
'Email notifications' => 'Epostvarslinger',
|
||||||
'Enable email notifications' => 'Aktiver eposvarslinger',
|
'Enable email notifications' => 'Aktiver epostvarslinger',
|
||||||
'Task position:' => 'Oppgaveposisjon:',
|
'Task position:' => 'Oppgaveposisjon:',
|
||||||
'The task #%d have been opened.' => 'Oppgaven #%d er åpnet.',
|
'The task #%d have been opened.' => 'Oppgaven #%d er åpnet.',
|
||||||
'The task #%d have been closed.' => 'Oppgaven #%d er lukket.',
|
'The task #%d have been closed.' => 'Oppgaven #%d er lukket.',
|
||||||
|
@ -382,12 +382,12 @@ return array(
|
||||||
'Disable public access' => 'Deaktiver offentlig tilgang',
|
'Disable public access' => 'Deaktiver offentlig tilgang',
|
||||||
'Enable public access' => 'Aktiver offentlig tilgang',
|
'Enable public access' => 'Aktiver offentlig tilgang',
|
||||||
'Public access disabled' => 'Offentlig tilgang er deaktivert',
|
'Public access disabled' => 'Offentlig tilgang er deaktivert',
|
||||||
'Do you really want to disable this project: "%s"?' => 'Vil du virkelig deaktivere prosjektet: "%s"?',
|
'Do you really want to disable this project: "%s"?' => 'Vil du deaktivere prosjektet: "%s"?',
|
||||||
'Do you really want to enable this project: "%s"?' => 'Vil du virkelig aktivere prosjektet: "%s"?',
|
'Do you really want to enable this project: "%s"?' => 'Vil du aktivere prosjektet: "%s"?',
|
||||||
'Project activation' => 'Prosjekt aktivering',
|
'Project activation' => 'Prosjekt aktivering',
|
||||||
'Move the task to another project' => 'Flytt oppgaven til et annet prosjekt',
|
'Move the task to another project' => 'Flytt oppgaven til et annet prosjekt',
|
||||||
'Move to another project' => 'Flytt til et annet prosjekt',
|
'Move to another project' => 'Flytt til et annet prosjekt',
|
||||||
'Do you really want to duplicate this task?' => 'Vil du virkelig kopiere denne oppgaven?',
|
'Do you really want to duplicate this task?' => 'Vil du kopiere denne oppgaven?',
|
||||||
'Duplicate a task' => 'Kopier en oppgave',
|
'Duplicate a task' => 'Kopier en oppgave',
|
||||||
'External accounts' => 'Eksterne kontoer',
|
'External accounts' => 'Eksterne kontoer',
|
||||||
'Account type' => 'Kontotype',
|
'Account type' => 'Kontotype',
|
||||||
|
@ -395,8 +395,6 @@ return array(
|
||||||
'Remote' => 'Fjernstyrt',
|
'Remote' => 'Fjernstyrt',
|
||||||
'Enabled' => 'Aktiv',
|
'Enabled' => 'Aktiv',
|
||||||
'Disabled' => 'Deaktivert',
|
'Disabled' => 'Deaktivert',
|
||||||
'Google account linked' => 'Google-konto knyttet',
|
|
||||||
'Github account linked' => 'GitHub-konto knyttet',
|
|
||||||
'Username:' => 'Brukernavn',
|
'Username:' => 'Brukernavn',
|
||||||
'Name:' => 'Navn:',
|
'Name:' => 'Navn:',
|
||||||
'Email:' => 'Epost:',
|
'Email:' => 'Epost:',
|
||||||
|
@ -411,7 +409,7 @@ return array(
|
||||||
'External authentications' => 'Ekstern godkjenning',
|
'External authentications' => 'Ekstern godkjenning',
|
||||||
'Google Account' => 'Google-konto',
|
'Google Account' => 'Google-konto',
|
||||||
'Github Account' => 'GitHub-konto',
|
'Github Account' => 'GitHub-konto',
|
||||||
'Never connected.' => 'Aldri knyttet.',
|
'Never connected.' => 'Aldri innlogget.',
|
||||||
'No account linked.' => 'Ingen kontoer knyttet.',
|
'No account linked.' => 'Ingen kontoer knyttet.',
|
||||||
'Account linked.' => 'Konto knyttet.',
|
'Account linked.' => 'Konto knyttet.',
|
||||||
'No external authentication enabled.' => 'Ingen eksterne godkjenninger aktiveret.',
|
'No external authentication enabled.' => 'Ingen eksterne godkjenninger aktiveret.',
|
||||||
|
@ -466,7 +464,7 @@ return array(
|
||||||
'Database' => 'Database',
|
'Database' => 'Database',
|
||||||
'About' => 'Om',
|
'About' => 'Om',
|
||||||
'Database driver:' => 'Database driver:',
|
'Database driver:' => 'Database driver:',
|
||||||
'Board settings' => 'Innstillinger for ptosjektside',
|
'Board settings' => 'Innstillinger for prosjektside',
|
||||||
'URL and token' => 'URL og token',
|
'URL and token' => 'URL og token',
|
||||||
'Webhook settings' => 'Webhook innstillinger',
|
'Webhook settings' => 'Webhook innstillinger',
|
||||||
'URL for task creation:' => 'URL for oppgaveopprettelse:',
|
'URL for task creation:' => 'URL for oppgaveopprettelse:',
|
||||||
|
@ -475,9 +473,9 @@ return array(
|
||||||
'Refresh interval for private board' => 'Oppdateringsintervall for privat hovedside',
|
'Refresh interval for private board' => 'Oppdateringsintervall for privat hovedside',
|
||||||
'Refresh interval for public board' => 'Oppdateringsintervall for offentlig hovedside',
|
'Refresh interval for public board' => 'Oppdateringsintervall for offentlig hovedside',
|
||||||
'Task highlight period' => 'Fremhevingsperiode for oppgave',
|
'Task highlight period' => 'Fremhevingsperiode for oppgave',
|
||||||
'Period (in second) to consider a task was modified recently (0 to disable, 2 days by default)' => 'Periode for å anta at en oppgave nylig ble endretg (0 for å deaktivere, 2 dager som standard)',
|
'Period (in second) to consider a task was modified recently (0 to disable, 2 days by default)' => 'Periode for ø anta at en oppgave nylig ble endretg (0 for å deaktivere, 2 dager som standard)',
|
||||||
'Frequency in second (60 seconds by default)' => 'Frekevens i sekunder (60 sekunder som standard)',
|
'Frequency in second (60 seconds by default)' => 'Frekevens i sekunder (60 sekunder som standard)',
|
||||||
'Frequency in second (0 to disable this feature, 10 seconds by default)' => 'Frekvens i sekunder (0 for å deaktivere denne funksjonen, 10 sekunder som standard)',
|
'Frequency in second (0 to disable this feature, 10 seconds by default)' => 'Frekvens i sekunder (0 for øt deaktivere denne funksjonen, 10 sekunder som standard)',
|
||||||
'Application URL' => 'Applikasjons URL',
|
'Application URL' => 'Applikasjons URL',
|
||||||
'Example: http://example.kanboard.net/ (used by email notifications)' => 'Eksempel: http://example.kanboard.net/ (bruges til email notifikationer)',
|
'Example: http://example.kanboard.net/ (used by email notifications)' => 'Eksempel: http://example.kanboard.net/ (bruges til email notifikationer)',
|
||||||
'Token regenerated.' => 'Token regenerert.',
|
'Token regenerated.' => 'Token regenerert.',
|
||||||
|
@ -485,7 +483,7 @@ return array(
|
||||||
'ISO format is always accepted, example: "%s" and "%s"' => 'ISO format er alltid akseptert, eksempelvis: "%s" og "%s"',
|
'ISO format is always accepted, example: "%s" and "%s"' => 'ISO format er alltid akseptert, eksempelvis: "%s" og "%s"',
|
||||||
'New private project' => 'Nytt privat prosjekt',
|
'New private project' => 'Nytt privat prosjekt',
|
||||||
'This project is private' => 'Dette projektet er privat',
|
'This project is private' => 'Dette projektet er privat',
|
||||||
'Type here to create a new sub-task' => 'Skriv her for å opprette en ny deloppgave',
|
'Type here to create a new sub-task' => 'Skriv her for ø opprette en ny deloppgave',
|
||||||
'Add' => 'Legg til',
|
'Add' => 'Legg til',
|
||||||
'Estimated time: %s hours' => 'Estimert tid: %s timer',
|
'Estimated time: %s hours' => 'Estimert tid: %s timer',
|
||||||
'Time spent: %s hours' => 'Tid brukt: %s timer',
|
'Time spent: %s hours' => 'Tid brukt: %s timer',
|
||||||
|
@ -510,21 +508,21 @@ return array(
|
||||||
'Columns' => 'Kolonner',
|
'Columns' => 'Kolonner',
|
||||||
'Task' => 'Oppgave',
|
'Task' => 'Oppgave',
|
||||||
// 'Your are not member of any project.' => '',
|
// 'Your are not member of any project.' => '',
|
||||||
// 'Percentage' => '',
|
'Percentage' => 'Prosent',
|
||||||
// 'Number of tasks' => '',
|
'Number of tasks' => 'Antall oppgaver',
|
||||||
// 'Task distribution' => '',
|
'Task distribution' => 'Kolonnefordeling',
|
||||||
// 'Reportings' => '',
|
'Reportings' => 'Rapportering',
|
||||||
// 'Task repartition for "%s"' => '',
|
// 'Task repartition for "%s"' => '',
|
||||||
'Analytics' => 'Analyser',
|
'Analytics' => 'Analyser',
|
||||||
// 'Subtask' => '',
|
'Subtask' => 'Deloppgave',
|
||||||
'My subtasks' => 'Mine deloppgaver',
|
'My subtasks' => 'Mine deloppgaver',
|
||||||
// 'User repartition' => '',
|
'User repartition' => 'Brukerfordeling',
|
||||||
// 'User repartition for "%s"' => '',
|
// 'User repartition for "%s"' => '',
|
||||||
'Clone this project' => 'Kopier dette prosjektet',
|
'Clone this project' => 'Kopier dette prosjektet',
|
||||||
// 'Column removed successfully.' => '',
|
'Column removed successfully.' => 'Kolonne flyttet',
|
||||||
// 'Github Issue' => '',
|
// 'Github Issue' => '',
|
||||||
// 'Not enough data to show the graph.' => '',
|
// 'Not enough data to show the graph.' => '',
|
||||||
// 'Previous' => '',
|
'Previous' => 'Forrige',
|
||||||
// 'The id must be an integer' => '',
|
// 'The id must be an integer' => '',
|
||||||
// 'The project id must be an integer' => '',
|
// 'The project id must be an integer' => '',
|
||||||
// 'The status must be an integer' => '',
|
// 'The status must be an integer' => '',
|
||||||
|
@ -536,9 +534,9 @@ return array(
|
||||||
// 'This value is required' => '',
|
// 'This value is required' => '',
|
||||||
// 'This value must be numeric' => '',
|
// 'This value must be numeric' => '',
|
||||||
// 'Unable to create this task.' => '',
|
// 'Unable to create this task.' => '',
|
||||||
// 'Cumulative flow diagram' => '',
|
'Cumulative flow diagram' => 'Kumulativt flytdiagram',
|
||||||
// 'Cumulative flow diagram for "%s"' => '',
|
// 'Cumulative flow diagram for "%s"' => '',
|
||||||
// 'Daily project summary' => '',
|
'Daily project summary' => 'Daglig prosjektsammendrag',
|
||||||
// 'Daily project summary export' => '',
|
// 'Daily project summary export' => '',
|
||||||
// 'Daily project summary export for "%s"' => '',
|
// 'Daily project summary export for "%s"' => '',
|
||||||
'Exports' => 'Eksporter',
|
'Exports' => 'Eksporter',
|
||||||
|
@ -546,7 +544,7 @@ return array(
|
||||||
'Nothing to preview...' => 'Ingenting å forhåndsvise',
|
'Nothing to preview...' => 'Ingenting å forhåndsvise',
|
||||||
'Preview' => 'Forhåndsvisning',
|
'Preview' => 'Forhåndsvisning',
|
||||||
'Write' => 'Skriv',
|
'Write' => 'Skriv',
|
||||||
'Active swimlanes' => 'Aktive svæmmebaner',
|
'Active swimlanes' => 'Aktive svømmebaner',
|
||||||
'Add a new swimlane' => 'Legg til en ny svømmebane',
|
'Add a new swimlane' => 'Legg til en ny svømmebane',
|
||||||
'Change default swimlane' => 'Endre standard svømmebane',
|
'Change default swimlane' => 'Endre standard svømmebane',
|
||||||
'Default swimlane' => 'Standard svømmebane',
|
'Default swimlane' => 'Standard svømmebane',
|
||||||
|
@ -558,10 +556,10 @@ return array(
|
||||||
'Rename' => 'Endre navn',
|
'Rename' => 'Endre navn',
|
||||||
'Show default swimlane' => 'Vis standard svømmebane',
|
'Show default swimlane' => 'Vis standard svømmebane',
|
||||||
// 'Swimlane modification for the project "%s"' => '',
|
// 'Swimlane modification for the project "%s"' => '',
|
||||||
// 'Swimlane not found.' => '',
|
'Swimlane not found.' => 'Svømmebane ikke funnet',
|
||||||
// 'Swimlane removed successfully.' => '',
|
'Swimlane removed successfully.' => 'Svømmebane fjernet',
|
||||||
'Swimlanes' => 'Svømmebaner',
|
'Swimlanes' => 'Svømmebaner',
|
||||||
'Swimlane updated successfully.' => 'Svæmmebane oppdatert',
|
'Swimlane updated successfully.' => 'Svømmebane oppdatert',
|
||||||
// 'The default swimlane have been updated successfully.' => '',
|
// 'The default swimlane have been updated successfully.' => '',
|
||||||
// 'Unable to create your swimlane.' => '',
|
// 'Unable to create your swimlane.' => '',
|
||||||
// 'Unable to remove this swimlane.' => '',
|
// 'Unable to remove this swimlane.' => '',
|
||||||
|
@ -576,27 +574,27 @@ return array(
|
||||||
// 'Help on Gitlab webhooks' => '',
|
// 'Help on Gitlab webhooks' => '',
|
||||||
'Integrations' => 'Integrasjoner',
|
'Integrations' => 'Integrasjoner',
|
||||||
'Integration with third-party services' => 'Integrasjoner med tredje-parts tjenester',
|
'Integration with third-party services' => 'Integrasjoner med tredje-parts tjenester',
|
||||||
// 'Role for this project' => '',
|
'Role for this project' => 'Rolle for dette prosjektet',
|
||||||
'Project manager' => 'Prosjektleder',
|
'Project manager' => 'Prosjektleder',
|
||||||
'Project member' => 'Prosjektmedlem',
|
'Project member' => 'Prosjektmedlem',
|
||||||
'A project manager can change the settings of the project and have more privileges than a standard user.' => 'Prosjektlederen kan endre flere innstillinger for prosjektet enn den en vanlig bruker kan.',
|
'A project manager can change the settings of the project and have more privileges than a standard user.' => 'Prosjektlederen kan endre flere innstillinger for prosjektet enn den en vanlig bruker kan.',
|
||||||
// 'Gitlab Issue' => '',
|
// 'Gitlab Issue' => '',
|
||||||
// 'Subtask Id' => '',
|
'Subtask Id' => 'Deloppgave ID',
|
||||||
// 'Subtasks' => '',
|
'Subtasks' => 'Deloppgaver',
|
||||||
// 'Subtasks Export' => '',
|
'Subtasks Export' => 'Eksporter deloppgaver',
|
||||||
// 'Subtasks exportation for "%s"' => '',
|
// 'Subtasks exportation for "%s"' => '',
|
||||||
// 'Task Title' => '',
|
'Task Title' => 'Oppgavetittel',
|
||||||
// 'Untitled' => '',
|
// 'Untitled' => '',
|
||||||
'Application default' => 'Standardinstilling',
|
'Application default' => 'Standardinstilling',
|
||||||
'Language:' => 'Språk',
|
'Language:' => 'Språk',
|
||||||
'Timezone:' => 'Tidssone',
|
'Timezone:' => 'Tidssone',
|
||||||
// 'All columns' => '',
|
'All columns' => 'Alle kolonner',
|
||||||
'Calendar' => 'Kalender',
|
'Calendar' => 'Kalender',
|
||||||
// 'Next' => '',
|
'Next' => 'Neste',
|
||||||
// '#%d' => '',
|
// '#%d' => '',
|
||||||
// 'All swimlanes' => '',
|
'All swimlanes' => 'Alle svømmebaner',
|
||||||
// 'All colors' => '',
|
'All colors' => 'Alle farger',
|
||||||
// 'All status' => '',
|
'All status' => 'Alle statuser',
|
||||||
// 'Moved to column %s' => '',
|
// 'Moved to column %s' => '',
|
||||||
'Change description' => 'Endre beskrivelse',
|
'Change description' => 'Endre beskrivelse',
|
||||||
'User dashboard' => 'Brukerens hovedside',
|
'User dashboard' => 'Brukerens hovedside',
|
||||||
|
@ -612,8 +610,8 @@ return array(
|
||||||
// 'Bitbucket commit received' => '',
|
// 'Bitbucket commit received' => '',
|
||||||
// 'Bitbucket webhooks' => '',
|
// 'Bitbucket webhooks' => '',
|
||||||
// 'Help on Bitbucket webhooks' => '',
|
// 'Help on Bitbucket webhooks' => '',
|
||||||
// 'Start' => '',
|
'Start' => 'Start',
|
||||||
// 'End' => '',
|
'End' => 'Slutt',
|
||||||
'Task age in days' => 'Dager siden oppgaven ble opprettet',
|
'Task age in days' => 'Dager siden oppgaven ble opprettet',
|
||||||
'Days in this column' => 'Dager siden oppgaven ble lagt i denne kolonnen',
|
'Days in this column' => 'Dager siden oppgaven ble lagt i denne kolonnen',
|
||||||
// '%dd' => '',
|
// '%dd' => '',
|
||||||
|
@ -621,7 +619,7 @@ return array(
|
||||||
'Add a new link' => 'Legg til en ny relasjon',
|
'Add a new link' => 'Legg til en ny relasjon',
|
||||||
// 'Do you really want to remove this link: "%s"?' => '',
|
// 'Do you really want to remove this link: "%s"?' => '',
|
||||||
// 'Do you really want to remove this link with task #%d?' => '',
|
// 'Do you really want to remove this link with task #%d?' => '',
|
||||||
// 'Field required' => '',
|
'Field required' => 'Feltet må fylles ut',
|
||||||
'Link added successfully.' => 'Ny relasjon er lagt til',
|
'Link added successfully.' => 'Ny relasjon er lagt til',
|
||||||
'Link updated successfully.' => 'Relasjon er oppdatert',
|
'Link updated successfully.' => 'Relasjon er oppdatert',
|
||||||
'Link removed successfully.' => 'Relasjon er fjernet',
|
'Link removed successfully.' => 'Relasjon er fjernet',
|
||||||
|
@ -667,75 +665,26 @@ return array(
|
||||||
'Horizontal scrolling' => 'Bla horisontalt',
|
'Horizontal scrolling' => 'Bla horisontalt',
|
||||||
'Compact/wide view' => 'Kompakt/bred visning',
|
'Compact/wide view' => 'Kompakt/bred visning',
|
||||||
'No results match:' => 'Ingen resultater',
|
'No results match:' => 'Ingen resultater',
|
||||||
// 'Remove hourly rate' => '',
|
|
||||||
// 'Do you really want to remove this hourly rate?' => '',
|
|
||||||
'Hourly rates' => 'Timepriser',
|
|
||||||
'Hourly rate' => 'Timepris',
|
|
||||||
'Currency' => 'Valuta',
|
'Currency' => 'Valuta',
|
||||||
// 'Effective date' => '',
|
|
||||||
// 'Add new rate' => '',
|
|
||||||
// 'Rate removed successfully.' => '',
|
|
||||||
// 'Unable to remove this rate.' => '',
|
|
||||||
// 'Unable to save the hourly rate.' => '',
|
|
||||||
// 'Hourly rate created successfully.' => '',
|
|
||||||
// 'Start time' => '',
|
|
||||||
// 'End time' => '',
|
|
||||||
// 'Comment' => '',
|
|
||||||
// 'All day' => '',
|
|
||||||
// 'Day' => '',
|
|
||||||
'Manage timetable' => 'Tidstabell',
|
|
||||||
'Overtime timetable' => 'Overtidstabell',
|
|
||||||
'Time off timetable' => 'Fritidstabell',
|
|
||||||
'Timetable' => 'Tidstabell',
|
|
||||||
'Work timetable' => 'Arbeidstidstabell',
|
|
||||||
'Week timetable' => 'Uketidstabell',
|
|
||||||
'Day timetable' => 'Dagtidstabell',
|
|
||||||
'From' => 'Fra',
|
|
||||||
'To' => 'Til',
|
|
||||||
// 'Time slot created successfully.' => '',
|
|
||||||
// 'Unable to save this time slot.' => '',
|
|
||||||
// 'Time slot removed successfully.' => '',
|
|
||||||
// 'Unable to remove this time slot.' => '',
|
|
||||||
// 'Do you really want to remove this time slot?' => '',
|
|
||||||
// 'Remove time slot' => '',
|
|
||||||
// 'Add new time slot' => '',
|
|
||||||
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
|
|
||||||
'Files' => 'Filer',
|
'Files' => 'Filer',
|
||||||
'Images' => 'Bilder',
|
'Images' => 'Bilder',
|
||||||
'Private project' => 'Privat prosjekt',
|
'Private project' => 'Privat prosjekt',
|
||||||
// 'Amount' => '',
|
|
||||||
// 'AUD - Australian Dollar' => '',
|
// 'AUD - Australian Dollar' => '',
|
||||||
'Budget' => 'Budsjett',
|
|
||||||
// 'Budget line' => '',
|
|
||||||
// 'Budget line removed successfully.' => '',
|
|
||||||
// 'Budget lines' => '',
|
|
||||||
// 'CAD - Canadian Dollar' => '',
|
// 'CAD - Canadian Dollar' => '',
|
||||||
// 'CHF - Swiss Francs' => '',
|
// 'CHF - Swiss Francs' => '',
|
||||||
// 'Cost' => '',
|
|
||||||
// 'Cost breakdown' => '',
|
|
||||||
// 'Custom Stylesheet' => '',
|
// 'Custom Stylesheet' => '',
|
||||||
// 'download' => '',
|
'download' => 'last ned',
|
||||||
// 'Do you really want to remove this budget line?' => '',
|
|
||||||
// 'EUR - Euro' => '',
|
// 'EUR - Euro' => '',
|
||||||
// 'Expenses' => '',
|
|
||||||
// 'GBP - British Pound' => '',
|
// 'GBP - British Pound' => '',
|
||||||
// 'INR - Indian Rupee' => '',
|
// 'INR - Indian Rupee' => '',
|
||||||
// 'JPY - Japanese Yen' => '',
|
// 'JPY - Japanese Yen' => '',
|
||||||
// 'New budget line' => '',
|
|
||||||
// 'NZD - New Zealand Dollar' => '',
|
// 'NZD - New Zealand Dollar' => '',
|
||||||
// 'Remove a budget line' => '',
|
|
||||||
// 'Remove budget line' => '',
|
|
||||||
// 'RSD - Serbian dinar' => '',
|
// 'RSD - Serbian dinar' => '',
|
||||||
// 'The budget line have been created successfully.' => '',
|
|
||||||
// 'Unable to create the budget line.' => '',
|
|
||||||
// 'Unable to remove this budget line.' => '',
|
|
||||||
// 'USD - US Dollar' => '',
|
// 'USD - US Dollar' => '',
|
||||||
// 'Remaining' => '',
|
'Destination column' => 'Ny kolonne',
|
||||||
// 'Destination column' => '',
|
|
||||||
'Move the task to another column when assigned to a user' => 'Flytt oppgaven til en annen kolonne når den er tildelt en bruker',
|
'Move the task to another column when assigned to a user' => 'Flytt oppgaven til en annen kolonne når den er tildelt en bruker',
|
||||||
'Move the task to another column when assignee is cleared' => 'Flytt oppgaven til en annen kolonne når ppgavetildeling fjernes ',
|
'Move the task to another column when assignee is cleared' => 'Flytt oppgaven til en annen kolonne når ppgavetildeling fjernes ',
|
||||||
// 'Source column' => '',
|
'Source column' => 'Opprinnelig kolonne',
|
||||||
// 'Show subtask estimates (forecast of future work)' => '',
|
|
||||||
'Transitions' => 'Statusendringer',
|
'Transitions' => 'Statusendringer',
|
||||||
// 'Executer' => '',
|
// 'Executer' => '',
|
||||||
// 'Time spent in the column' => '',
|
// 'Time spent in the column' => '',
|
||||||
|
@ -746,7 +695,6 @@ return array(
|
||||||
// 'Rate' => '',
|
// 'Rate' => '',
|
||||||
// 'Change reference currency' => '',
|
// 'Change reference currency' => '',
|
||||||
// 'Add a new currency rate' => '',
|
// 'Add a new currency rate' => '',
|
||||||
// 'Currency rates are used to calculate project budget.' => '',
|
|
||||||
// 'Reference currency' => '',
|
// 'Reference currency' => '',
|
||||||
// 'The currency rate have been added successfully.' => '',
|
// 'The currency rate have been added successfully.' => '',
|
||||||
// 'Unable to add this currency rate.' => '',
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
@ -782,7 +730,7 @@ return array(
|
||||||
// 'This chart show the task complexity over the time (Work Remaining).' => '',
|
// 'This chart show the task complexity over the time (Work Remaining).' => '',
|
||||||
// 'Screenshot taken %s' => '',
|
// 'Screenshot taken %s' => '',
|
||||||
'Add a screenshot' => 'Legg til et skjermbilde',
|
'Add a screenshot' => 'Legg til et skjermbilde',
|
||||||
'Take a screenshot and press CTRL+V or ⌘+V to paste here.' => 'Ta et skjermbilde og trykk CTRL+V for å lime det inn her.',
|
'Take a screenshot and press CTRL+V or â+V to paste here.' => 'Ta et skjermbilde og trykk CTRL+V for å lime det inn her.',
|
||||||
'Screenshot uploaded successfully.' => 'Skjermbilde opplastet',
|
'Screenshot uploaded successfully.' => 'Skjermbilde opplastet',
|
||||||
// 'SEK - Swedish Krona' => '',
|
// 'SEK - Swedish Krona' => '',
|
||||||
'The project identifier is an optional alphanumeric code used to identify your project.' => 'Prosjektkoden er en alfanumerisk kode som kan brukes for å identifisere prosjektet',
|
'The project identifier is an optional alphanumeric code used to identify your project.' => 'Prosjektkoden er en alfanumerisk kode som kan brukes for å identifisere prosjektet',
|
||||||
|
@ -853,7 +801,7 @@ return array(
|
||||||
// 'There is no user management for private projects.' => '',
|
// 'There is no user management for private projects.' => '',
|
||||||
// 'User that will receive the email' => '',
|
// 'User that will receive the email' => '',
|
||||||
// 'Email subject' => '',
|
// 'Email subject' => '',
|
||||||
// 'Date' => '',
|
'Date' => 'Dato',
|
||||||
// 'By @%s on Bitbucket' => '',
|
// 'By @%s on Bitbucket' => '',
|
||||||
// 'Bitbucket Issue' => '',
|
// 'Bitbucket Issue' => '',
|
||||||
// 'Commit made by @%s on Bitbucket' => '',
|
// 'Commit made by @%s on Bitbucket' => '',
|
||||||
|
@ -877,10 +825,7 @@ return array(
|
||||||
'Notification' => 'Varsel',
|
'Notification' => 'Varsel',
|
||||||
// '%s moved the task #%d to the first swimlane' => '',
|
// '%s moved the task #%d to the first swimlane' => '',
|
||||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||||
// 'Swimlane' => '',
|
'Swimlane' => 'Svømmebane',
|
||||||
// 'Budget overview' => '',
|
|
||||||
// 'Type' => '',
|
|
||||||
// 'There is not enough data to show something.' => '',
|
|
||||||
// 'Gravatar' => '',
|
// 'Gravatar' => '',
|
||||||
// 'Hipchat' => '',
|
// 'Hipchat' => '',
|
||||||
// 'Slack' => '',
|
// 'Slack' => '',
|
||||||
|
@ -908,19 +853,19 @@ return array(
|
||||||
// 'The field "%s" have been updated' => '',
|
// 'The field "%s" have been updated' => '',
|
||||||
// 'The description have been modified' => '',
|
// 'The description have been modified' => '',
|
||||||
// 'Do you really want to close the task "%s" as well as all subtasks?' => '',
|
// 'Do you really want to close the task "%s" as well as all subtasks?' => '',
|
||||||
// 'Swimlane: %s' => '',
|
'Swimlane: %s' => 'Svømmebane: %s',
|
||||||
// 'I want to receive notifications for:' => '',
|
'I want to receive notifications for:' => 'Jeg vil motta varslinger om:',
|
||||||
'All tasks' => 'Alle oppgaver',
|
'All tasks' => 'Alle oppgaver',
|
||||||
// 'Only for tasks assigned to me' => '',
|
'Only for tasks assigned to me' => 'Kun oppgaver som er tildelt meg',
|
||||||
// 'Only for tasks created by me' => '',
|
'Only for tasks created by me' => 'Kun oppgaver som er opprettet av meg',
|
||||||
// 'Only for tasks created by me and assigned to me' => '',
|
'Only for tasks created by me and assigned to me' => 'Kun oppgaver som er opprettet av meg og tildelt meg',
|
||||||
// '%A' => '',
|
// '%A' => '',
|
||||||
// '%b %e, %Y, %k:%M %p' => '',
|
// '%b %e, %Y, %k:%M %p' => '',
|
||||||
// 'New due date: %B %e, %Y' => '',
|
// 'New due date: %B %e, %Y' => '',
|
||||||
// 'Start date changed: %B %e, %Y' => '',
|
// 'Start date changed: %B %e, %Y' => '',
|
||||||
// '%k:%M %p' => '',
|
// '%k:%M %p' => '',
|
||||||
// '%%Y-%%m-%%d' => '',
|
// '%%Y-%%m-%%d' => '',
|
||||||
// 'Total for all columns' => '',
|
'Total for all columns' => 'Totalt for alle kolonner',
|
||||||
// 'You need at least 2 days of data to show the chart.' => '',
|
// 'You need at least 2 days of data to show the chart.' => '',
|
||||||
// '<15m' => '',
|
// '<15m' => '',
|
||||||
// '<30m' => '',
|
// '<30m' => '',
|
||||||
|
@ -928,41 +873,41 @@ return array(
|
||||||
'Start timer' => 'Start timer',
|
'Start timer' => 'Start timer',
|
||||||
'Add project member' => 'Legg til prosjektmedlem',
|
'Add project member' => 'Legg til prosjektmedlem',
|
||||||
'Enable notifications' => 'Aktiver varslinger',
|
'Enable notifications' => 'Aktiver varslinger',
|
||||||
// 'My activity stream' => '',
|
'My activity stream' => 'Aktivitetslogg',
|
||||||
// 'My calendar' => '',
|
'My calendar' => 'Min kalender',
|
||||||
// 'Search tasks' => '',
|
'Search tasks' => 'Søk oppgave',
|
||||||
// 'Back to the calendar' => '',
|
'Back to the calendar' => 'Tilbake til kalender',
|
||||||
// 'Filters' => '',
|
'Filters' => 'Filtere',
|
||||||
// 'Reset filters' => '',
|
'Reset filters' => 'Nullstill filter',
|
||||||
// 'My tasks due tomorrow' => '',
|
'My tasks due tomorrow' => 'Mine oppgaver med frist i morgen',
|
||||||
// 'Tasks due today' => '',
|
'Tasks due today' => 'Oppgaver med frist i dag',
|
||||||
// 'Tasks due tomorrow' => '',
|
'Tasks due tomorrow' => 'Oppgaver med frist i morgen',
|
||||||
// 'Tasks due yesterday' => '',
|
'Tasks due yesterday' => 'Oppgaver med frist i går',
|
||||||
// 'Closed tasks' => '',
|
'Closed tasks' => 'Fullførte oppgaver',
|
||||||
// 'Open tasks' => '',
|
'Open tasks' => 'Åpne oppgaver',
|
||||||
// 'Not assigned' => '',
|
'Not assigned' => 'Ikke tildelt',
|
||||||
// 'View advanced search syntax' => '',
|
'View advanced search syntax' => 'Vis hjelp for avansert søk ',
|
||||||
// 'Overview' => '',
|
'Overview' => 'Oversikt',
|
||||||
// '%b %e %Y' => '',
|
// '%b %e %Y' => '',
|
||||||
// 'Board/Calendar/List view' => '',
|
'Board/Calendar/List view' => 'Oversikt/kalender/listevisning',
|
||||||
// 'Switch to the board view' => '',
|
'Switch to the board view' => 'Oversiktsvisning',
|
||||||
// 'Switch to the calendar view' => '',
|
'Switch to the calendar view' => 'Kalendevisning',
|
||||||
// 'Switch to the list view' => '',
|
'Switch to the list view' => 'Listevisning',
|
||||||
// 'Go to the search/filter box' => '',
|
'Go to the search/filter box' => 'Gå til søk/filter',
|
||||||
// 'There is no activity yet.' => '',
|
'There is no activity yet.' => 'Ingen aktiviteter ennå.',
|
||||||
// 'No tasks found.' => '',
|
'No tasks found.' => 'Ingen oppgaver funnet',
|
||||||
// 'Keyboard shortcut: "%s"' => '',
|
'Keyboard shortcut: "%s"' => 'Hurtigtaster: "%s"',
|
||||||
// 'List' => '',
|
'List' => 'Liste',
|
||||||
// 'Filter' => '',
|
'Filter' => 'Filter',
|
||||||
// 'Advanced search' => '',
|
'Advanced search' => 'Avansert søk',
|
||||||
// 'Example of query: ' => '',
|
'Example of query: ' => 'Eksempel på spørring',
|
||||||
// 'Search by project: ' => '',
|
'Search by project: ' => 'Søk etter prosjekt',
|
||||||
// 'Search by column: ' => '',
|
'Search by column: ' => 'Søk etter kolonne',
|
||||||
// 'Search by assignee: ' => '',
|
'Search by assignee: ' => 'Søk etter tildelt',
|
||||||
// 'Search by color: ' => '',
|
'Search by color: ' => 'Søk etter farge',
|
||||||
// 'Search by category: ' => '',
|
'Search by category: ' => 'Søk etter kategori',
|
||||||
// 'Search by description: ' => '',
|
'Search by description: ' => 'Søk etter beskrivelse',
|
||||||
// 'Search by due date: ' => '',
|
'Search by due date: ' => 'Søk etter frist',
|
||||||
// 'Lead and Cycle time for "%s"' => '',
|
// 'Lead and Cycle time for "%s"' => '',
|
||||||
// 'Average time spent into each column for "%s"' => '',
|
// 'Average time spent into each column for "%s"' => '',
|
||||||
// 'Average time spent into each column' => '',
|
// 'Average time spent into each column' => '',
|
||||||
|
@ -996,75 +941,119 @@ return array(
|
||||||
// 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '',
|
// 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '',
|
||||||
// 'By @%s on Gitlab' => '',
|
// 'By @%s on Gitlab' => '',
|
||||||
// 'Gitlab issue comment created' => '',
|
// 'Gitlab issue comment created' => '',
|
||||||
// 'New remote user' => '',
|
'New remote user' => 'Ny eksternbruker',
|
||||||
// 'New local user' => '',
|
'New local user' => 'Ny internbruker',
|
||||||
// 'Default task color' => '',
|
'Default task color' => 'Standard oppgavefarge',
|
||||||
// 'Hide sidebar' => '',
|
'Hide sidebar' => 'Skjul sidemeny',
|
||||||
// 'Expand sidebar' => '',
|
'Expand sidebar' => 'Vis sidemeny',
|
||||||
// 'This feature does not work with all browsers.' => '',
|
// 'This feature does not work with all browsers.' => '',
|
||||||
// 'There is no destination project available.' => '',
|
// 'There is no destination project available.' => '',
|
||||||
// 'Trigger automatically subtask time tracking' => '',
|
// 'Trigger automatically subtask time tracking' => '',
|
||||||
// 'Include closed tasks in the cumulative flow diagram' => '',
|
// 'Include closed tasks in the cumulative flow diagram' => '',
|
||||||
// 'Current swimlane: %s' => '',
|
'Current swimlane: %s' => 'Nåværende svømmebane: %s',
|
||||||
// 'Current column: %s' => '',
|
'Current column: %s' => 'Nåværende kolonne: %s',
|
||||||
// 'Current category: %s' => '',
|
'Current category: %s' => ': %s',
|
||||||
// 'no category' => '',
|
'no category' => 'ingen kategori',
|
||||||
// 'Current assignee: %s' => '',
|
'Current assignee: %s' => 'Tildelt til %s',
|
||||||
// 'not assigned' => '',
|
'not assigned' => 'ikke tildelt',
|
||||||
// 'Author:' => '',
|
'Author:' => 'Opprettet av',
|
||||||
// 'contributors' => '',
|
'contributors' => 'bidragsytere',
|
||||||
// 'License:' => '',
|
'License:' => 'Lisens:',
|
||||||
// 'License' => '',
|
'License' => 'Lisens',
|
||||||
// 'Project Administrator' => '',
|
'Project Administrator' => 'Prosjektadministrator',
|
||||||
// 'Enter the text below' => '',
|
'Enter the text below' => 'Legg inn teksten nedenfor',
|
||||||
// 'Gantt chart for %s' => '',
|
'Gantt chart for %s' => 'Gantt skjema for %s',
|
||||||
// 'Sort by position' => '',
|
// 'Sort by position' => '',
|
||||||
// 'Sort by date' => '',
|
'Sort by date' => 'Sorter etter dato',
|
||||||
// 'Add task' => '',
|
'Add task' => 'Legg til oppgave',
|
||||||
// 'Start date:' => '',
|
'Start date:' => 'Startdato:',
|
||||||
// 'Due date:' => '',
|
'Due date:' => 'Frist:',
|
||||||
// 'There is no start date or due date for this task.' => '',
|
'There is no start date or due date for this task.' => 'Det er ingen startdato eller frist for denne oppgaven',
|
||||||
// 'Moving or resizing a task will change the start and due date of the task.' => '',
|
// 'Moving or resizing a task will change the start and due date of the task.' => '',
|
||||||
// 'There is no task in your project.' => '',
|
'There is no task in your project.' => 'Det er ingen oppgaver i dette prosjektet',
|
||||||
// 'Gantt chart' => '',
|
'Gantt chart' => 'Gantt skjema',
|
||||||
// 'People who are project managers' => '',
|
'People who are project managers' => 'Prosjektledere',
|
||||||
// 'People who are project members' => '',
|
'People who are project members' => 'Prosjektmedlemmer',
|
||||||
// 'NOK - Norwegian Krone' => '',
|
// 'NOK - Norwegian Krone' => '',
|
||||||
// 'Show this column' => '',
|
'Show this column' => 'Vis denne kolonnen',
|
||||||
// 'Hide this column' => '',
|
'Hide this column' => 'Skjul denne kolonnen',
|
||||||
// 'open file' => '',
|
'open file' => 'Åpne fil',
|
||||||
// 'End date' => '',
|
'End date' => 'Sluttdato',
|
||||||
// 'Users overview' => '',
|
'Users overview' => 'Brukeroversikt',
|
||||||
// 'Managers' => '',
|
'Managers' => 'Ledere',
|
||||||
// 'Members' => '',
|
'Members' => 'Medlemmer',
|
||||||
// 'Shared project' => '',
|
'Shared project' => 'Delt prosjekt',
|
||||||
// 'Project managers' => '',
|
'Project managers' => 'Prosjektledere',
|
||||||
// 'Project members' => '',
|
'Project members' => 'Prosjektmedlemmer',
|
||||||
// 'Gantt chart for all projects' => '',
|
// 'Gantt chart for all projects' => '',
|
||||||
// 'Projects list' => '',
|
'Projects list' => 'Prosjektliste',
|
||||||
// 'Gantt chart for this project' => '',
|
'Gantt chart for this project' => 'Gantt skjema for dette prosjektet',
|
||||||
// 'Project board' => '',
|
'Project board' => 'Prosjektsiden',
|
||||||
// 'End date:' => '',
|
'End date:' => 'Sluttdato:',
|
||||||
// 'There is no start date or end date for this project.' => '',
|
// 'There is no start date or end date for this project.' => '',
|
||||||
// 'Projects Gantt chart' => '',
|
'Projects Gantt chart' => 'Gantt skjema for prosjekter',
|
||||||
// 'Start date: %s' => '',
|
'Start date: %s' => 'Startdato: %s',
|
||||||
// 'End date: %s' => '',
|
'End date: %s' => 'Sluttdato: %s',
|
||||||
// 'Link type' => '',
|
'Link type' => 'Relasjonstype',
|
||||||
// 'Change task color when using a specific task link' => '',
|
// 'Change task color when using a specific task link' => '',
|
||||||
// 'Task link creation or modification' => '',
|
// 'Task link creation or modification' => '',
|
||||||
// 'Login with my Gitlab Account' => '',
|
// 'Login with my Gitlab Account' => '',
|
||||||
// 'Milestone' => '',
|
'Milestone' => 'Milepæl',
|
||||||
// 'Gitlab Authentication' => '',
|
// 'Gitlab Authentication' => '',
|
||||||
// 'Help on Gitlab authentication' => '',
|
// 'Help on Gitlab authentication' => '',
|
||||||
// 'Gitlab Id' => '',
|
// 'Gitlab Id' => '',
|
||||||
// 'Gitlab Account' => '',
|
// 'Gitlab Account' => '',
|
||||||
// 'Link my Gitlab Account' => '',
|
// 'Link my Gitlab Account' => '',
|
||||||
// 'Unlink my Gitlab Account' => '',
|
// 'Unlink my Gitlab Account' => '',
|
||||||
// 'Documentation: %s' => '',
|
'Documentation: %s' => 'Dokumentasjon: %s',
|
||||||
// 'Switch to the Gantt chart view' => '',
|
'Switch to the Gantt chart view' => 'Gantt skjema visning',
|
||||||
// 'Reset the search/filter box' => '',
|
'Reset the search/filter box' => 'Nullstill søk/filter',
|
||||||
// 'Documentation' => '',
|
'Documentation' => 'Dokumentasjon',
|
||||||
// 'Table of contents' => '',
|
'Table of contents' => 'Innholdsfortegnelse',
|
||||||
// 'Gantt' => '',
|
'Gantt' => 'Gantt',
|
||||||
// 'Help with project permissions' => '',
|
'Help with project permissions' => 'Hjelp med prosjekttilganger',
|
||||||
|
// 'Author' => '',
|
||||||
|
// 'Version' => '',
|
||||||
|
// 'Plugins' => '',
|
||||||
|
// 'There is no plugin loaded.' => '',
|
||||||
|
// 'Set maximum column height' => '',
|
||||||
|
// 'Remove maximum column height' => '',
|
||||||
|
// 'My notifications' => '',
|
||||||
|
// 'Custom filters' => '',
|
||||||
|
// 'Your custom filter have been created successfully.' => '',
|
||||||
|
// 'Unable to create your custom filter.' => '',
|
||||||
|
// 'Custom filter removed successfully.' => '',
|
||||||
|
// 'Unable to remove this custom filter.' => '',
|
||||||
|
// 'Edit custom filter' => '',
|
||||||
|
// 'Your custom filter have been updated successfully.' => '',
|
||||||
|
// 'Unable to update custom filter.' => '',
|
||||||
|
// 'Web' => '',
|
||||||
|
// 'New attachment on task #%d: %s' => '',
|
||||||
|
// 'New comment on task #%d' => '',
|
||||||
|
// 'Comment updated on task #%d' => '',
|
||||||
|
// 'New subtask on task #%d' => '',
|
||||||
|
// 'Subtask updated on task #%d' => '',
|
||||||
|
// 'New task #%d: %s' => '',
|
||||||
|
// 'Task updated #%d' => '',
|
||||||
|
// 'Task #%d closed' => '',
|
||||||
|
// 'Task #%d opened' => '',
|
||||||
|
// 'Column changed for task #%d' => '',
|
||||||
|
// 'New position for task #%d' => '',
|
||||||
|
// 'Swimlane changed for task #%d' => '',
|
||||||
|
// 'Assignee changed on task #%d' => '',
|
||||||
|
// '%d overdue tasks' => '',
|
||||||
|
// 'Task #%d is overdue' => '',
|
||||||
|
// 'No new notifications.' => '',
|
||||||
|
// 'Mark all as read' => '',
|
||||||
|
// 'Mark as read' => '',
|
||||||
|
// 'Total number of tasks in this column across all swimlanes' => '',
|
||||||
|
// 'Collapse swimlane' => '',
|
||||||
|
// 'Expand swimlane' => '',
|
||||||
|
// 'Add a new filter' => '',
|
||||||
|
// 'Share with all project members' => '',
|
||||||
|
// 'Shared' => '',
|
||||||
|
// 'Owner' => '',
|
||||||
|
// 'Unread notifications' => '',
|
||||||
|
// 'My filters' => '',
|
||||||
|
// 'Notification methods:' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -313,7 +313,7 @@ return array(
|
||||||
'Estimate:' => 'Schatting :',
|
'Estimate:' => 'Schatting :',
|
||||||
'Spent:' => 'Besteed :',
|
'Spent:' => 'Besteed :',
|
||||||
'Do you really want to remove this sub-task?' => 'Weet u zeker dat u deze subtaak wil verwijderen ?',
|
'Do you really want to remove this sub-task?' => 'Weet u zeker dat u deze subtaak wil verwijderen ?',
|
||||||
'Remaining:' => 'Restant :',
|
'Remaining:' => 'Resterend :',
|
||||||
'hours' => 'uren',
|
'hours' => 'uren',
|
||||||
'spent' => 'besteed',
|
'spent' => 'besteed',
|
||||||
'estimated' => 'geschat',
|
'estimated' => 'geschat',
|
||||||
|
@ -395,8 +395,6 @@ return array(
|
||||||
'Remote' => 'Remote',
|
'Remote' => 'Remote',
|
||||||
'Enabled' => 'Actief',
|
'Enabled' => 'Actief',
|
||||||
'Disabled' => 'Inactief',
|
'Disabled' => 'Inactief',
|
||||||
'Google account linked' => 'Gelinkt Google Account',
|
|
||||||
'Github account linked' => 'Gelinkt Github Account',
|
|
||||||
'Username:' => 'Gebruikersnaam :',
|
'Username:' => 'Gebruikersnaam :',
|
||||||
'Name:' => 'Naam :',
|
'Name:' => 'Naam :',
|
||||||
'Email:' => 'Email :',
|
'Email:' => 'Email :',
|
||||||
|
@ -667,75 +665,26 @@ return array(
|
||||||
// 'Horizontal scrolling' => '',
|
// 'Horizontal scrolling' => '',
|
||||||
// 'Compact/wide view' => '',
|
// 'Compact/wide view' => '',
|
||||||
// 'No results match:' => '',
|
// 'No results match:' => '',
|
||||||
// 'Remove hourly rate' => '',
|
|
||||||
// 'Do you really want to remove this hourly rate?' => '',
|
|
||||||
// 'Hourly rates' => '',
|
|
||||||
// 'Hourly rate' => '',
|
|
||||||
// 'Currency' => '',
|
// 'Currency' => '',
|
||||||
// 'Effective date' => '',
|
|
||||||
// 'Add new rate' => '',
|
|
||||||
// 'Rate removed successfully.' => '',
|
|
||||||
// 'Unable to remove this rate.' => '',
|
|
||||||
// 'Unable to save the hourly rate.' => '',
|
|
||||||
// 'Hourly rate created successfully.' => '',
|
|
||||||
// 'Start time' => '',
|
|
||||||
// 'End time' => '',
|
|
||||||
// 'Comment' => '',
|
|
||||||
// 'All day' => '',
|
|
||||||
// 'Day' => '',
|
|
||||||
// 'Manage timetable' => '',
|
|
||||||
// 'Overtime timetable' => '',
|
|
||||||
// 'Time off timetable' => '',
|
|
||||||
// 'Timetable' => '',
|
|
||||||
// 'Work timetable' => '',
|
|
||||||
// 'Week timetable' => '',
|
|
||||||
// 'Day timetable' => '',
|
|
||||||
// 'From' => '',
|
|
||||||
// 'To' => '',
|
|
||||||
// 'Time slot created successfully.' => '',
|
|
||||||
// 'Unable to save this time slot.' => '',
|
|
||||||
// 'Time slot removed successfully.' => '',
|
|
||||||
// 'Unable to remove this time slot.' => '',
|
|
||||||
// 'Do you really want to remove this time slot?' => '',
|
|
||||||
// 'Remove time slot' => '',
|
|
||||||
// 'Add new time slot' => '',
|
|
||||||
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
|
|
||||||
// 'Files' => '',
|
// 'Files' => '',
|
||||||
// 'Images' => '',
|
// 'Images' => '',
|
||||||
// 'Private project' => '',
|
// 'Private project' => '',
|
||||||
// 'Amount' => '',
|
|
||||||
// 'AUD - Australian Dollar' => '',
|
// 'AUD - Australian Dollar' => '',
|
||||||
// 'Budget' => '',
|
|
||||||
// 'Budget line' => '',
|
|
||||||
// 'Budget line removed successfully.' => '',
|
|
||||||
// 'Budget lines' => '',
|
|
||||||
// 'CAD - Canadian Dollar' => '',
|
// 'CAD - Canadian Dollar' => '',
|
||||||
// 'CHF - Swiss Francs' => '',
|
// 'CHF - Swiss Francs' => '',
|
||||||
// 'Cost' => '',
|
|
||||||
// 'Cost breakdown' => '',
|
|
||||||
// 'Custom Stylesheet' => '',
|
// 'Custom Stylesheet' => '',
|
||||||
// 'download' => '',
|
// 'download' => '',
|
||||||
// 'Do you really want to remove this budget line?' => '',
|
|
||||||
// 'EUR - Euro' => '',
|
// 'EUR - Euro' => '',
|
||||||
// 'Expenses' => '',
|
|
||||||
// 'GBP - British Pound' => '',
|
// 'GBP - British Pound' => '',
|
||||||
// 'INR - Indian Rupee' => '',
|
// 'INR - Indian Rupee' => '',
|
||||||
// 'JPY - Japanese Yen' => '',
|
// 'JPY - Japanese Yen' => '',
|
||||||
// 'New budget line' => '',
|
|
||||||
// 'NZD - New Zealand Dollar' => '',
|
// 'NZD - New Zealand Dollar' => '',
|
||||||
// 'Remove a budget line' => '',
|
|
||||||
// 'Remove budget line' => '',
|
|
||||||
// 'RSD - Serbian dinar' => '',
|
// 'RSD - Serbian dinar' => '',
|
||||||
// 'The budget line have been created successfully.' => '',
|
|
||||||
// 'Unable to create the budget line.' => '',
|
|
||||||
// 'Unable to remove this budget line.' => '',
|
|
||||||
// 'USD - US Dollar' => '',
|
// 'USD - US Dollar' => '',
|
||||||
// 'Remaining' => '',
|
|
||||||
// 'Destination column' => '',
|
// 'Destination column' => '',
|
||||||
// 'Move the task to another column when assigned to a user' => '',
|
// 'Move the task to another column when assigned to a user' => '',
|
||||||
// 'Move the task to another column when assignee is cleared' => '',
|
// 'Move the task to another column when assignee is cleared' => '',
|
||||||
// 'Source column' => '',
|
// 'Source column' => '',
|
||||||
// 'Show subtask estimates (forecast of future work)' => '',
|
|
||||||
// 'Transitions' => '',
|
// 'Transitions' => '',
|
||||||
// 'Executer' => '',
|
// 'Executer' => '',
|
||||||
// 'Time spent in the column' => '',
|
// 'Time spent in the column' => '',
|
||||||
|
@ -746,7 +695,6 @@ return array(
|
||||||
// 'Rate' => '',
|
// 'Rate' => '',
|
||||||
// 'Change reference currency' => '',
|
// 'Change reference currency' => '',
|
||||||
// 'Add a new currency rate' => '',
|
// 'Add a new currency rate' => '',
|
||||||
// 'Currency rates are used to calculate project budget.' => '',
|
|
||||||
// 'Reference currency' => '',
|
// 'Reference currency' => '',
|
||||||
// 'The currency rate have been added successfully.' => '',
|
// 'The currency rate have been added successfully.' => '',
|
||||||
// 'Unable to add this currency rate.' => '',
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
@ -878,9 +826,6 @@ return array(
|
||||||
// '%s moved the task #%d to the first swimlane' => '',
|
// '%s moved the task #%d to the first swimlane' => '',
|
||||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||||
// 'Swimlane' => '',
|
// 'Swimlane' => '',
|
||||||
// 'Budget overview' => '',
|
|
||||||
// 'Type' => '',
|
|
||||||
// 'There is not enough data to show something.' => '',
|
|
||||||
// 'Gravatar' => '',
|
// 'Gravatar' => '',
|
||||||
// 'Hipchat' => '',
|
// 'Hipchat' => '',
|
||||||
// 'Slack' => '',
|
// 'Slack' => '',
|
||||||
|
@ -1067,4 +1012,48 @@ return array(
|
||||||
// 'Table of contents' => '',
|
// 'Table of contents' => '',
|
||||||
// 'Gantt' => '',
|
// 'Gantt' => '',
|
||||||
// 'Help with project permissions' => '',
|
// 'Help with project permissions' => '',
|
||||||
|
// 'Author' => '',
|
||||||
|
// 'Version' => '',
|
||||||
|
// 'Plugins' => '',
|
||||||
|
// 'There is no plugin loaded.' => '',
|
||||||
|
// 'Set maximum column height' => '',
|
||||||
|
// 'Remove maximum column height' => '',
|
||||||
|
// 'My notifications' => '',
|
||||||
|
// 'Custom filters' => '',
|
||||||
|
// 'Your custom filter have been created successfully.' => '',
|
||||||
|
// 'Unable to create your custom filter.' => '',
|
||||||
|
// 'Custom filter removed successfully.' => '',
|
||||||
|
// 'Unable to remove this custom filter.' => '',
|
||||||
|
// 'Edit custom filter' => '',
|
||||||
|
// 'Your custom filter have been updated successfully.' => '',
|
||||||
|
// 'Unable to update custom filter.' => '',
|
||||||
|
// 'Web' => '',
|
||||||
|
// 'New attachment on task #%d: %s' => '',
|
||||||
|
// 'New comment on task #%d' => '',
|
||||||
|
// 'Comment updated on task #%d' => '',
|
||||||
|
// 'New subtask on task #%d' => '',
|
||||||
|
// 'Subtask updated on task #%d' => '',
|
||||||
|
// 'New task #%d: %s' => '',
|
||||||
|
// 'Task updated #%d' => '',
|
||||||
|
// 'Task #%d closed' => '',
|
||||||
|
// 'Task #%d opened' => '',
|
||||||
|
// 'Column changed for task #%d' => '',
|
||||||
|
// 'New position for task #%d' => '',
|
||||||
|
// 'Swimlane changed for task #%d' => '',
|
||||||
|
// 'Assignee changed on task #%d' => '',
|
||||||
|
// '%d overdue tasks' => '',
|
||||||
|
// 'Task #%d is overdue' => '',
|
||||||
|
// 'No new notifications.' => '',
|
||||||
|
// 'Mark all as read' => '',
|
||||||
|
// 'Mark as read' => '',
|
||||||
|
// 'Total number of tasks in this column across all swimlanes' => '',
|
||||||
|
// 'Collapse swimlane' => '',
|
||||||
|
// 'Expand swimlane' => '',
|
||||||
|
// 'Add a new filter' => '',
|
||||||
|
// 'Share with all project members' => '',
|
||||||
|
// 'Shared' => '',
|
||||||
|
// 'Owner' => '',
|
||||||
|
// 'Unread notifications' => '',
|
||||||
|
// 'My filters' => '',
|
||||||
|
// 'Notification methods:' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -395,8 +395,6 @@ return array(
|
||||||
'Remote' => 'Zdalne',
|
'Remote' => 'Zdalne',
|
||||||
'Enabled' => 'Odblokowane',
|
'Enabled' => 'Odblokowane',
|
||||||
'Disabled' => 'Zablokowane',
|
'Disabled' => 'Zablokowane',
|
||||||
'Google account linked' => 'Połączone konto Google',
|
|
||||||
'Github account linked' => 'Połączone konto Github',
|
|
||||||
'Username:' => 'Nazwa Użytkownika:',
|
'Username:' => 'Nazwa Użytkownika:',
|
||||||
'Name:' => 'Imię i Nazwisko',
|
'Name:' => 'Imię i Nazwisko',
|
||||||
'Email:' => 'Email: ',
|
'Email:' => 'Email: ',
|
||||||
|
@ -667,75 +665,26 @@ return array(
|
||||||
'Horizontal scrolling' => 'Przewijanie poziome',
|
'Horizontal scrolling' => 'Przewijanie poziome',
|
||||||
'Compact/wide view' => 'Pełny/Kompaktowy widok',
|
'Compact/wide view' => 'Pełny/Kompaktowy widok',
|
||||||
'No results match:' => 'Brak wyników:',
|
'No results match:' => 'Brak wyników:',
|
||||||
'Remove hourly rate' => 'Usuń stawkę godzinową',
|
|
||||||
'Do you really want to remove this hourly rate?' => 'Czy na pewno chcesz usunąć stawkę godzinową?',
|
|
||||||
'Hourly rates' => 'Stawki godzinowe',
|
|
||||||
'Hourly rate' => 'Stawka godzinowa',
|
|
||||||
'Currency' => 'Waluta',
|
'Currency' => 'Waluta',
|
||||||
'Effective date' => 'Data efektywna',
|
|
||||||
'Add new rate' => 'Dodaj nową stawkę',
|
|
||||||
'Rate removed successfully.' => 'Stawka usunięta.',
|
|
||||||
'Unable to remove this rate.' => 'Nie można usunąć tej stawki.',
|
|
||||||
'Unable to save the hourly rate.' => 'Nie można zapisać tej stawki godzinowej.',
|
|
||||||
'Hourly rate created successfully.' => 'Stawka godzinowa utworzona pomyślnie.',
|
|
||||||
'Start time' => 'Rozpoczęto',
|
|
||||||
'End time' => 'Zakończono',
|
|
||||||
'Comment' => 'Komentarz',
|
|
||||||
'All day' => 'Cały dzień',
|
|
||||||
'Day' => 'Dzień',
|
|
||||||
'Manage timetable' => 'Zarządzaj rozkładami zajęć',
|
|
||||||
'Overtime timetable' => 'Rozkład zajęć - nadgodziny',
|
|
||||||
'Time off timetable' => 'Rozkład zajęć - czas wolny',
|
|
||||||
'Timetable' => 'Rozkład zajęć',
|
|
||||||
'Work timetable' => 'Rozkład zajęć - praca',
|
|
||||||
'Week timetable' => 'Tygodniowy rozkład zajęć',
|
|
||||||
'Day timetable' => 'Dzienny rozkład zajęć',
|
|
||||||
'From' => 'Od',
|
|
||||||
'To' => 'Do',
|
|
||||||
'Time slot created successfully.' => 'Przydział czasowy utworzony.',
|
|
||||||
'Unable to save this time slot.' => 'Nie można zapisać tego przydziału czasowego.',
|
|
||||||
'Time slot removed successfully.' => 'Przydział czasowy usunięty.',
|
|
||||||
'Unable to remove this time slot.' => 'Nie można usunąć tego przydziału czasowego.',
|
|
||||||
'Do you really want to remove this time slot?' => 'Czy na pewno chcesz usunąć ten przedział czasowy?',
|
|
||||||
'Remove time slot' => 'Usuń przedział czasowy',
|
|
||||||
'Add new time slot' => 'Dodaj przedział czasowy',
|
|
||||||
'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => 'Ten rozkład zajęć jest używany przypadku zaznaczenia "cały dzień" dla zaplanowanego czasu wolnego i nadgodzin',
|
|
||||||
'Files' => 'Pliki',
|
'Files' => 'Pliki',
|
||||||
'Images' => 'Obrazy',
|
'Images' => 'Obrazy',
|
||||||
'Private project' => 'Projekt prywatny',
|
'Private project' => 'Projekt prywatny',
|
||||||
'Amount' => 'Ilość',
|
|
||||||
'AUD - Australian Dollar' => 'AUD - Dolar australijski',
|
'AUD - Australian Dollar' => 'AUD - Dolar australijski',
|
||||||
'Budget' => 'Budżet',
|
|
||||||
'Budget line' => 'Linia budżetowa',
|
|
||||||
'Budget line removed successfully.' => 'Linia budżetowa usunięta.',
|
|
||||||
'Budget lines' => 'Linie budżetowe',
|
|
||||||
'CAD - Canadian Dollar' => 'CAD - Dolar kanadyjski',
|
'CAD - Canadian Dollar' => 'CAD - Dolar kanadyjski',
|
||||||
'CHF - Swiss Francs' => 'CHF - Frank szwajcarski',
|
'CHF - Swiss Francs' => 'CHF - Frank szwajcarski',
|
||||||
'Cost' => 'Koszt',
|
|
||||||
'Cost breakdown' => 'Analiza kosztów',
|
|
||||||
'Custom Stylesheet' => 'Niestandardowy arkusz stylów',
|
'Custom Stylesheet' => 'Niestandardowy arkusz stylów',
|
||||||
'download' => 'pobierz',
|
'download' => 'pobierz',
|
||||||
'Do you really want to remove this budget line?' => 'Czy chcesz usunąć tą linię budżetową?',
|
|
||||||
// 'EUR - Euro' => '',
|
// 'EUR - Euro' => '',
|
||||||
'Expenses' => 'Wydatki',
|
|
||||||
'GBP - British Pound' => 'GBP - Funt brytyjski',
|
'GBP - British Pound' => 'GBP - Funt brytyjski',
|
||||||
'INR - Indian Rupee' => 'INR - Rupia indyjska',
|
'INR - Indian Rupee' => 'INR - Rupia indyjska',
|
||||||
'JPY - Japanese Yen' => 'JPY - Jen japoński',
|
'JPY - Japanese Yen' => 'JPY - Jen japoński',
|
||||||
'New budget line' => 'Nowa linia budżetowa',
|
|
||||||
'NZD - New Zealand Dollar' => 'NZD - Dolar nowozelandzki',
|
'NZD - New Zealand Dollar' => 'NZD - Dolar nowozelandzki',
|
||||||
'Remove a budget line' => 'Usuń linię budżetową',
|
|
||||||
'Remove budget line' => 'Usuń linię budżetową',
|
|
||||||
'RSD - Serbian dinar' => 'RSD - Dinar serbski',
|
'RSD - Serbian dinar' => 'RSD - Dinar serbski',
|
||||||
// 'The budget line have been created successfully.' => '',
|
|
||||||
'Unable to create the budget line.' => 'Nie można utworzyć linii budżetowej',
|
|
||||||
'Unable to remove this budget line.' => 'Nie można usunąć tej linii budżetowej',
|
|
||||||
'USD - US Dollar' => 'USD - Dolar amerykański',
|
'USD - US Dollar' => 'USD - Dolar amerykański',
|
||||||
'Remaining' => 'Pozostało',
|
|
||||||
'Destination column' => 'Kolumna docelowa',
|
'Destination column' => 'Kolumna docelowa',
|
||||||
'Move the task to another column when assigned to a user' => 'Przenieś zadanie do innej kolumny gdy zostanie przypisane do osoby',
|
'Move the task to another column when assigned to a user' => 'Przenieś zadanie do innej kolumny gdy zostanie przypisane do osoby',
|
||||||
'Move the task to another column when assignee is cleared' => 'Przenieś zadanie do innej kolumny gdy osoba odpowiedzialna zostanie usunięta',
|
'Move the task to another column when assignee is cleared' => 'Przenieś zadanie do innej kolumny gdy osoba odpowiedzialna zostanie usunięta',
|
||||||
'Source column' => 'Kolumna źródłowa',
|
'Source column' => 'Kolumna źródłowa',
|
||||||
'Show subtask estimates (forecast of future work)' => 'Pokaż planowane czasy wykonania pod-zadań',
|
|
||||||
'Transitions' => 'Przeniesienia',
|
'Transitions' => 'Przeniesienia',
|
||||||
'Executer' => 'Wykonał',
|
'Executer' => 'Wykonał',
|
||||||
'Time spent in the column' => 'Czas spędzony w tej kolumnie',
|
'Time spent in the column' => 'Czas spędzony w tej kolumnie',
|
||||||
|
@ -746,7 +695,6 @@ return array(
|
||||||
'Rate' => 'Kurs',
|
'Rate' => 'Kurs',
|
||||||
'Change reference currency' => 'Zmień walutę referencyjną',
|
'Change reference currency' => 'Zmień walutę referencyjną',
|
||||||
'Add a new currency rate' => 'Dodaj nowy kurs waluty',
|
'Add a new currency rate' => 'Dodaj nowy kurs waluty',
|
||||||
'Currency rates are used to calculate project budget.' => 'Kursy walut są używane do obliczeń budżetu projektu.',
|
|
||||||
'Reference currency' => 'Waluta referencyjna',
|
'Reference currency' => 'Waluta referencyjna',
|
||||||
'The currency rate have been added successfully.' => 'Dodano kurs waluty',
|
'The currency rate have been added successfully.' => 'Dodano kurs waluty',
|
||||||
'Unable to add this currency rate.' => 'Nie można dodać kursu waluty',
|
'Unable to add this currency rate.' => 'Nie można dodać kursu waluty',
|
||||||
|
@ -878,9 +826,6 @@ return array(
|
||||||
// '%s moved the task #%d to the first swimlane' => '',
|
// '%s moved the task #%d to the first swimlane' => '',
|
||||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||||
// 'Swimlane' => '',
|
// 'Swimlane' => '',
|
||||||
// 'Budget overview' => '',
|
|
||||||
// 'Type' => '',
|
|
||||||
// 'There is not enough data to show something.' => '',
|
|
||||||
// 'Gravatar' => '',
|
// 'Gravatar' => '',
|
||||||
// 'Hipchat' => '',
|
// 'Hipchat' => '',
|
||||||
// 'Slack' => '',
|
// 'Slack' => '',
|
||||||
|
@ -1067,4 +1012,48 @@ return array(
|
||||||
// 'Table of contents' => '',
|
// 'Table of contents' => '',
|
||||||
// 'Gantt' => '',
|
// 'Gantt' => '',
|
||||||
// 'Help with project permissions' => '',
|
// 'Help with project permissions' => '',
|
||||||
|
// 'Author' => '',
|
||||||
|
// 'Version' => '',
|
||||||
|
// 'Plugins' => '',
|
||||||
|
// 'There is no plugin loaded.' => '',
|
||||||
|
// 'Set maximum column height' => '',
|
||||||
|
// 'Remove maximum column height' => '',
|
||||||
|
// 'My notifications' => '',
|
||||||
|
// 'Custom filters' => '',
|
||||||
|
// 'Your custom filter have been created successfully.' => '',
|
||||||
|
// 'Unable to create your custom filter.' => '',
|
||||||
|
// 'Custom filter removed successfully.' => '',
|
||||||
|
// 'Unable to remove this custom filter.' => '',
|
||||||
|
// 'Edit custom filter' => '',
|
||||||
|
// 'Your custom filter have been updated successfully.' => '',
|
||||||
|
// 'Unable to update custom filter.' => '',
|
||||||
|
// 'Web' => '',
|
||||||
|
// 'New attachment on task #%d: %s' => '',
|
||||||
|
// 'New comment on task #%d' => '',
|
||||||
|
// 'Comment updated on task #%d' => '',
|
||||||
|
// 'New subtask on task #%d' => '',
|
||||||
|
// 'Subtask updated on task #%d' => '',
|
||||||
|
// 'New task #%d: %s' => '',
|
||||||
|
// 'Task updated #%d' => '',
|
||||||
|
// 'Task #%d closed' => '',
|
||||||
|
// 'Task #%d opened' => '',
|
||||||
|
// 'Column changed for task #%d' => '',
|
||||||
|
// 'New position for task #%d' => '',
|
||||||
|
// 'Swimlane changed for task #%d' => '',
|
||||||
|
// 'Assignee changed on task #%d' => '',
|
||||||
|
// '%d overdue tasks' => '',
|
||||||
|
// 'Task #%d is overdue' => '',
|
||||||
|
// 'No new notifications.' => '',
|
||||||
|
// 'Mark all as read' => '',
|
||||||
|
// 'Mark as read' => '',
|
||||||
|
// 'Total number of tasks in this column across all swimlanes' => '',
|
||||||
|
// 'Collapse swimlane' => '',
|
||||||
|
// 'Expand swimlane' => '',
|
||||||
|
// 'Add a new filter' => '',
|
||||||
|
// 'Share with all project members' => '',
|
||||||
|
// 'Shared' => '',
|
||||||
|
// 'Owner' => '',
|
||||||
|
// 'Unread notifications' => '',
|
||||||
|
// 'My filters' => '',
|
||||||
|
// 'Notification methods:' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -395,8 +395,6 @@ return array(
|
||||||
'Remote' => 'Remoto',
|
'Remote' => 'Remoto',
|
||||||
'Enabled' => 'Habilitado',
|
'Enabled' => 'Habilitado',
|
||||||
'Disabled' => 'Desabilitado',
|
'Disabled' => 'Desabilitado',
|
||||||
'Google account linked' => 'Conta do Google associada',
|
|
||||||
'Github account linked' => 'Conta do Github associada',
|
|
||||||
'Username:' => 'Usuário:',
|
'Username:' => 'Usuário:',
|
||||||
'Name:' => 'Nome:',
|
'Name:' => 'Nome:',
|
||||||
'Email:' => 'E-mail:',
|
'Email:' => 'E-mail:',
|
||||||
|
@ -667,75 +665,26 @@ return array(
|
||||||
'Horizontal scrolling' => 'Rolagem horizontal',
|
'Horizontal scrolling' => 'Rolagem horizontal',
|
||||||
'Compact/wide view' => 'Alternar entre a vista compacta e ampliada',
|
'Compact/wide view' => 'Alternar entre a vista compacta e ampliada',
|
||||||
'No results match:' => 'Nenhum resultado:',
|
'No results match:' => 'Nenhum resultado:',
|
||||||
'Remove hourly rate' => 'Retirar taxa horária',
|
|
||||||
'Do you really want to remove this hourly rate?' => 'Você deseja realmente remover esta taxa horária?',
|
|
||||||
'Hourly rates' => 'Taxas horárias',
|
|
||||||
'Hourly rate' => 'Taxa horária',
|
|
||||||
'Currency' => 'Moeda',
|
'Currency' => 'Moeda',
|
||||||
'Effective date' => 'Data efetiva',
|
|
||||||
'Add new rate' => 'Adicionar nova taxa',
|
|
||||||
'Rate removed successfully.' => 'Taxa removido com sucesso.',
|
|
||||||
'Unable to remove this rate.' => 'Impossível de remover esta taxa.',
|
|
||||||
'Unable to save the hourly rate.' => 'Impossível salvar a taxa horária.',
|
|
||||||
'Hourly rate created successfully.' => 'Taxa horária criada com sucesso.',
|
|
||||||
'Start time' => 'Horário de início',
|
|
||||||
'End time' => 'Horário de término',
|
|
||||||
'Comment' => 'comentário',
|
|
||||||
'All day' => 'Dia inteiro',
|
|
||||||
'Day' => 'Dia',
|
|
||||||
'Manage timetable' => 'Gestão dos horários',
|
|
||||||
'Overtime timetable' => 'Horas extras',
|
|
||||||
'Time off timetable' => 'Horas de ausência',
|
|
||||||
'Timetable' => 'Horários',
|
|
||||||
'Work timetable' => 'Horas trabalhadas',
|
|
||||||
'Week timetable' => 'Horário da semana',
|
|
||||||
'Day timetable' => 'Horário de un dia',
|
|
||||||
'From' => 'Desde',
|
|
||||||
'To' => 'A',
|
|
||||||
'Time slot created successfully.' => 'Intervalo de tempo criado com sucesso.',
|
|
||||||
'Unable to save this time slot.' => 'Impossível de guardar este intervalo de tempo.',
|
|
||||||
'Time slot removed successfully.' => 'Intervalo de tempo removido com sucesso.',
|
|
||||||
'Unable to remove this time slot.' => 'Impossível de remover esse intervalo de tempo.',
|
|
||||||
'Do you really want to remove this time slot?' => 'Você deseja realmente remover este intervalo de tempo?',
|
|
||||||
'Remove time slot' => 'Remover um intervalo de tempo',
|
|
||||||
'Add new time slot' => 'Adicionar um intervalo de tempo',
|
|
||||||
'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => 'Esses horários são usados quando a caixa de seleção "Dia inteiro" está marcada para Horas de ausência ou Extras',
|
|
||||||
'Files' => 'Arquivos',
|
'Files' => 'Arquivos',
|
||||||
'Images' => 'Imagens',
|
'Images' => 'Imagens',
|
||||||
'Private project' => 'Projeto privado',
|
'Private project' => 'Projeto privado',
|
||||||
'Amount' => 'Quantia',
|
|
||||||
'AUD - Australian Dollar' => 'AUD - Dólar australiano',
|
'AUD - Australian Dollar' => 'AUD - Dólar australiano',
|
||||||
'Budget' => 'Orçamento',
|
|
||||||
'Budget line' => 'Rubrica orçamental',
|
|
||||||
'Budget line removed successfully.' => 'Rubrica orçamental removida com sucesso',
|
|
||||||
'Budget lines' => 'Rubricas orçamentais',
|
|
||||||
'CAD - Canadian Dollar' => 'CAD - Dólar canadense',
|
'CAD - Canadian Dollar' => 'CAD - Dólar canadense',
|
||||||
'CHF - Swiss Francs' => 'CHF - Francos Suíços',
|
'CHF - Swiss Francs' => 'CHF - Francos Suíços',
|
||||||
'Cost' => 'Custo',
|
|
||||||
'Cost breakdown' => 'Repartição dos custos',
|
|
||||||
'Custom Stylesheet' => 'Folha de estilo personalizado',
|
'Custom Stylesheet' => 'Folha de estilo personalizado',
|
||||||
'download' => 'baixar',
|
'download' => 'baixar',
|
||||||
'Do you really want to remove this budget line?' => 'Você deseja realmente remover esta rubrica orçamental?',
|
|
||||||
'EUR - Euro' => 'EUR - Euro',
|
'EUR - Euro' => 'EUR - Euro',
|
||||||
'Expenses' => 'Despesas',
|
|
||||||
'GBP - British Pound' => 'GBP - Libra Esterlina',
|
'GBP - British Pound' => 'GBP - Libra Esterlina',
|
||||||
'INR - Indian Rupee' => 'INR - Rúpia indiana',
|
'INR - Indian Rupee' => 'INR - Rúpia indiana',
|
||||||
'JPY - Japanese Yen' => 'JPY - Iene japonês',
|
'JPY - Japanese Yen' => 'JPY - Iene japonês',
|
||||||
'New budget line' => 'Nova rubrica orçamental',
|
|
||||||
'NZD - New Zealand Dollar' => 'NZD - Dólar Neozelandês',
|
'NZD - New Zealand Dollar' => 'NZD - Dólar Neozelandês',
|
||||||
'Remove a budget line' => 'Remover uma rubrica orçamental',
|
|
||||||
'Remove budget line' => 'Remover uma rubrica orçamental',
|
|
||||||
'RSD - Serbian dinar' => 'RSD - Dinar sérvio',
|
'RSD - Serbian dinar' => 'RSD - Dinar sérvio',
|
||||||
'The budget line have been created successfully.' => 'A rubrica orçamental foi criada com sucesso.',
|
|
||||||
'Unable to create the budget line.' => 'Impossível de adicionar esta rubrica orçamental.',
|
|
||||||
'Unable to remove this budget line.' => 'Impossível de remover esta rubrica orçamental.',
|
|
||||||
'USD - US Dollar' => 'USD - Dólar norte-americano',
|
'USD - US Dollar' => 'USD - Dólar norte-americano',
|
||||||
'Remaining' => 'Restante',
|
|
||||||
'Destination column' => 'Coluna de destino',
|
'Destination column' => 'Coluna de destino',
|
||||||
'Move the task to another column when assigned to a user' => 'Mover a tarefa para uma outra coluna quando esta está atribuída a um usuário',
|
'Move the task to another column when assigned to a user' => 'Mover a tarefa para uma outra coluna quando esta está atribuída a um usuário',
|
||||||
'Move the task to another column when assignee is cleared' => 'Mover a tarefa para uma outra coluna quando esta não está atribuída',
|
'Move the task to another column when assignee is cleared' => 'Mover a tarefa para uma outra coluna quando esta não está atribuída',
|
||||||
'Source column' => 'Coluna de origem',
|
'Source column' => 'Coluna de origem',
|
||||||
'Show subtask estimates (forecast of future work)' => 'Mostrar a estimativa das subtarefas (previsão para o trabalho futuro)',
|
|
||||||
'Transitions' => 'Transições',
|
'Transitions' => 'Transições',
|
||||||
'Executer' => 'Executor(a)',
|
'Executer' => 'Executor(a)',
|
||||||
'Time spent in the column' => 'Tempo gasto na coluna',
|
'Time spent in the column' => 'Tempo gasto na coluna',
|
||||||
|
@ -746,7 +695,6 @@ return array(
|
||||||
'Rate' => 'Taxa',
|
'Rate' => 'Taxa',
|
||||||
'Change reference currency' => 'Mudar a moeda de referência',
|
'Change reference currency' => 'Mudar a moeda de referência',
|
||||||
'Add a new currency rate' => 'Adicionar uma nova taxa para uma moeda',
|
'Add a new currency rate' => 'Adicionar uma nova taxa para uma moeda',
|
||||||
'Currency rates are used to calculate project budget.' => 'As taxas de câmbio são utilizadas para calcular o orçamento do projeto.',
|
|
||||||
'Reference currency' => 'Moeda de Referência',
|
'Reference currency' => 'Moeda de Referência',
|
||||||
'The currency rate have been added successfully.' => 'A taxa de câmbio foi adicionada com sucesso.',
|
'The currency rate have been added successfully.' => 'A taxa de câmbio foi adicionada com sucesso.',
|
||||||
'Unable to add this currency rate.' => 'Impossível de adicionar essa taxa de câmbio.',
|
'Unable to add this currency rate.' => 'Impossível de adicionar essa taxa de câmbio.',
|
||||||
|
@ -878,9 +826,6 @@ return array(
|
||||||
'%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 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"',
|
'%s moved the task #%d to the swimlane "%s"' => '%s moveu a tarefa n° %d no swimlane "%s"',
|
||||||
'Swimlane' => 'Swimlane',
|
'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',
|
'Gravatar' => 'Gravatar',
|
||||||
'Hipchat' => 'Hipchat',
|
'Hipchat' => 'Hipchat',
|
||||||
'Slack' => 'Slack',
|
'Slack' => 'Slack',
|
||||||
|
@ -1060,11 +1005,55 @@ return array(
|
||||||
'Gitlab Account' => 'Conta Gitlab',
|
'Gitlab Account' => 'Conta Gitlab',
|
||||||
'Link my Gitlab Account' => 'Vincular minha conta Gitlab',
|
'Link my Gitlab Account' => 'Vincular minha conta Gitlab',
|
||||||
'Unlink my Gitlab Account' => 'Desvincular minha conta Gitlab',
|
'Unlink my Gitlab Account' => 'Desvincular minha conta Gitlab',
|
||||||
// 'Documentation: %s' => '',
|
'Documentation: %s' => 'Documentação: %s',
|
||||||
// 'Switch to the Gantt chart view' => '',
|
'Switch to the Gantt chart view' => 'Mudar para a vista gráfico de Gantt',
|
||||||
// 'Reset the search/filter box' => '',
|
'Reset the search/filter box' => 'Reiniciar o campo de pesquisa',
|
||||||
// 'Documentation' => '',
|
'Documentation' => 'Documentação',
|
||||||
// 'Table of contents' => '',
|
'Table of contents' => 'Índice',
|
||||||
// 'Gantt' => '',
|
'Gantt' => 'Gantt',
|
||||||
// 'Help with project permissions' => '',
|
'Help with project permissions' => 'Ajuda com as permissões dos projetos',
|
||||||
|
'Author' => 'Autor',
|
||||||
|
'Version' => 'Versão',
|
||||||
|
'Plugins' => 'Extensão',
|
||||||
|
'There is no plugin loaded.' => 'Não há nenhuma extensão carga.',
|
||||||
|
'Set maximum column height' => 'Definir a altura máxima das colunas',
|
||||||
|
'Remove maximum column height' => 'Retirar a altura máxima das colunas',
|
||||||
|
// 'My notifications' => '',
|
||||||
|
// 'Custom filters' => '',
|
||||||
|
// 'Your custom filter have been created successfully.' => '',
|
||||||
|
// 'Unable to create your custom filter.' => '',
|
||||||
|
// 'Custom filter removed successfully.' => '',
|
||||||
|
// 'Unable to remove this custom filter.' => '',
|
||||||
|
// 'Edit custom filter' => '',
|
||||||
|
// 'Your custom filter have been updated successfully.' => '',
|
||||||
|
// 'Unable to update custom filter.' => '',
|
||||||
|
// 'Web' => '',
|
||||||
|
// 'New attachment on task #%d: %s' => '',
|
||||||
|
// 'New comment on task #%d' => '',
|
||||||
|
// 'Comment updated on task #%d' => '',
|
||||||
|
// 'New subtask on task #%d' => '',
|
||||||
|
// 'Subtask updated on task #%d' => '',
|
||||||
|
// 'New task #%d: %s' => '',
|
||||||
|
// 'Task updated #%d' => '',
|
||||||
|
// 'Task #%d closed' => '',
|
||||||
|
// 'Task #%d opened' => '',
|
||||||
|
// 'Column changed for task #%d' => '',
|
||||||
|
// 'New position for task #%d' => '',
|
||||||
|
// 'Swimlane changed for task #%d' => '',
|
||||||
|
// 'Assignee changed on task #%d' => '',
|
||||||
|
// '%d overdue tasks' => '',
|
||||||
|
// 'Task #%d is overdue' => '',
|
||||||
|
// 'No new notifications.' => '',
|
||||||
|
// 'Mark all as read' => '',
|
||||||
|
// 'Mark as read' => '',
|
||||||
|
// 'Total number of tasks in this column across all swimlanes' => '',
|
||||||
|
// 'Collapse swimlane' => '',
|
||||||
|
// 'Expand swimlane' => '',
|
||||||
|
// 'Add a new filter' => '',
|
||||||
|
// 'Share with all project members' => '',
|
||||||
|
// 'Shared' => '',
|
||||||
|
// 'Owner' => '',
|
||||||
|
// 'Unread notifications' => '',
|
||||||
|
// 'My filters' => '',
|
||||||
|
// 'Notification methods:' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -395,8 +395,6 @@ return array(
|
||||||
'Remote' => 'Remoto',
|
'Remote' => 'Remoto',
|
||||||
'Enabled' => 'Activado',
|
'Enabled' => 'Activado',
|
||||||
'Disabled' => 'Desactivado',
|
'Disabled' => 'Desactivado',
|
||||||
'Google account linked' => 'Conta do Google associada',
|
|
||||||
'Github account linked' => 'Conta do Github associada',
|
|
||||||
'Username:' => 'Utilizador:',
|
'Username:' => 'Utilizador:',
|
||||||
'Name:' => 'Nome:',
|
'Name:' => 'Nome:',
|
||||||
'Email:' => 'E-mail:',
|
'Email:' => 'E-mail:',
|
||||||
|
@ -667,75 +665,26 @@ return array(
|
||||||
'Horizontal scrolling' => 'Deslocamento horizontal',
|
'Horizontal scrolling' => 'Deslocamento horizontal',
|
||||||
'Compact/wide view' => 'Alternar entre a vista compacta e ampliada',
|
'Compact/wide view' => 'Alternar entre a vista compacta e ampliada',
|
||||||
'No results match:' => 'Nenhum resultado:',
|
'No results match:' => 'Nenhum resultado:',
|
||||||
'Remove hourly rate' => 'Retirar taxa horária',
|
|
||||||
'Do you really want to remove this hourly rate?' => 'Tem a certeza que quer remover esta taxa horária?',
|
|
||||||
'Hourly rates' => 'Taxas horárias',
|
|
||||||
'Hourly rate' => 'Taxa horária',
|
|
||||||
'Currency' => 'Moeda',
|
'Currency' => 'Moeda',
|
||||||
'Effective date' => 'Data efectiva',
|
|
||||||
'Add new rate' => 'Adicionar nova taxa',
|
|
||||||
'Rate removed successfully.' => 'Taxa removido com sucesso.',
|
|
||||||
'Unable to remove this rate.' => 'Impossível de remover esta taxa.',
|
|
||||||
'Unable to save the hourly rate.' => 'Impossível salvar a taxa horária.',
|
|
||||||
'Hourly rate created successfully.' => 'Taxa horária criada com sucesso.',
|
|
||||||
'Start time' => 'Horário de início',
|
|
||||||
'End time' => 'Horário de término',
|
|
||||||
'Comment' => 'comentário',
|
|
||||||
'All day' => 'Dia inteiro',
|
|
||||||
'Day' => 'Dia',
|
|
||||||
'Manage timetable' => 'Gestão dos horários',
|
|
||||||
'Overtime timetable' => 'Horas extras',
|
|
||||||
'Time off timetable' => 'Horas de ausência',
|
|
||||||
'Timetable' => 'Horários',
|
|
||||||
'Work timetable' => 'Horas trabalhadas',
|
|
||||||
'Week timetable' => 'Horário da semana',
|
|
||||||
'Day timetable' => 'Horário de um dia',
|
|
||||||
'From' => 'Desde',
|
|
||||||
'To' => 'A',
|
|
||||||
'Time slot created successfully.' => 'Intervalo de tempo criado com sucesso.',
|
|
||||||
'Unable to save this time slot.' => 'Impossível guardar este intervalo de tempo.',
|
|
||||||
'Time slot removed successfully.' => 'Intervalo de tempo removido com sucesso.',
|
|
||||||
'Unable to remove this time slot.' => 'Impossível remover esse intervalo de tempo.',
|
|
||||||
'Do you really want to remove this time slot?' => 'Tem a certeza que quer remover este intervalo de tempo?',
|
|
||||||
'Remove time slot' => 'Remover um intervalo de tempo',
|
|
||||||
'Add new time slot' => 'Adicionar um intervalo de tempo',
|
|
||||||
'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => 'Esses horários são usados quando a caixa de seleção "Dia inteiro" está marcada para Horas de ausência ou Extras',
|
|
||||||
'Files' => 'Arquivos',
|
'Files' => 'Arquivos',
|
||||||
'Images' => 'Imagens',
|
'Images' => 'Imagens',
|
||||||
'Private project' => 'Projecto privado',
|
'Private project' => 'Projecto privado',
|
||||||
'Amount' => 'Quantia',
|
|
||||||
'AUD - Australian Dollar' => 'AUD - Dólar australiano',
|
'AUD - Australian Dollar' => 'AUD - Dólar australiano',
|
||||||
'Budget' => 'Orçamento',
|
|
||||||
'Budget line' => 'Rubrica orçamental',
|
|
||||||
'Budget line removed successfully.' => 'Rubrica orçamental removida com sucesso',
|
|
||||||
'Budget lines' => 'Rubricas orçamentais',
|
|
||||||
'CAD - Canadian Dollar' => 'CAD - Dólar canadense',
|
'CAD - Canadian Dollar' => 'CAD - Dólar canadense',
|
||||||
'CHF - Swiss Francs' => 'CHF - Francos Suíços',
|
'CHF - Swiss Francs' => 'CHF - Francos Suíços',
|
||||||
'Cost' => 'Custo',
|
|
||||||
'Cost breakdown' => 'Repartição dos custos',
|
|
||||||
'Custom Stylesheet' => 'Folha de estilos personalizada',
|
'Custom Stylesheet' => 'Folha de estilos personalizada',
|
||||||
'download' => 'transferir',
|
'download' => 'transferir',
|
||||||
'Do you really want to remove this budget line?' => 'Tem a certeza que quer remover esta rubrica orçamental?',
|
|
||||||
'EUR - Euro' => 'EUR - Euro',
|
'EUR - Euro' => 'EUR - Euro',
|
||||||
'Expenses' => 'Despesas',
|
|
||||||
'GBP - British Pound' => 'GBP - Libra Esterlina',
|
'GBP - British Pound' => 'GBP - Libra Esterlina',
|
||||||
'INR - Indian Rupee' => 'INR - Rúpia indiana',
|
'INR - Indian Rupee' => 'INR - Rúpia indiana',
|
||||||
'JPY - Japanese Yen' => 'JPY - Iene japonês',
|
'JPY - Japanese Yen' => 'JPY - Iene japonês',
|
||||||
'New budget line' => 'Nova rubrica orçamental',
|
|
||||||
'NZD - New Zealand Dollar' => 'NZD - Dólar Neozelandês',
|
'NZD - New Zealand Dollar' => 'NZD - Dólar Neozelandês',
|
||||||
'Remove a budget line' => 'Remover uma rubrica orçamental',
|
|
||||||
'Remove budget line' => 'Remover uma rubrica orçamental',
|
|
||||||
'RSD - Serbian dinar' => 'RSD - Dinar sérvio',
|
'RSD - Serbian dinar' => 'RSD - Dinar sérvio',
|
||||||
'The budget line have been created successfully.' => 'A rubrica orçamental foi criada com sucesso.',
|
|
||||||
'Unable to create the budget line.' => 'Impossível adicionar esta rubrica orçamental.',
|
|
||||||
'Unable to remove this budget line.' => 'Impossível remover esta rubrica orçamental.',
|
|
||||||
'USD - US Dollar' => 'USD - Dólar norte-americano',
|
'USD - US Dollar' => 'USD - Dólar norte-americano',
|
||||||
'Remaining' => 'Restante',
|
|
||||||
'Destination column' => 'Coluna de destino',
|
'Destination column' => 'Coluna de destino',
|
||||||
'Move the task to another column when assigned to a user' => 'Mover a tarefa para uma outra coluna quando esta está atribuída a um utilizador',
|
'Move the task to another column when assigned to a user' => 'Mover a tarefa para uma outra coluna quando esta está atribuída a um utilizador',
|
||||||
'Move the task to another column when assignee is cleared' => 'Mover a tarefa para uma outra coluna quando esta não está atribuída',
|
'Move the task to another column when assignee is cleared' => 'Mover a tarefa para uma outra coluna quando esta não está atribuída',
|
||||||
'Source column' => 'Coluna de origem',
|
'Source column' => 'Coluna de origem',
|
||||||
'Show subtask estimates (forecast of future work)' => 'Mostrar a estimativa das subtarefas (previsão para o trabalho futuro)',
|
|
||||||
'Transitions' => 'Transições',
|
'Transitions' => 'Transições',
|
||||||
'Executer' => 'Executor(a)',
|
'Executer' => 'Executor(a)',
|
||||||
'Time spent in the column' => 'Tempo gasto na coluna',
|
'Time spent in the column' => 'Tempo gasto na coluna',
|
||||||
|
@ -746,7 +695,6 @@ return array(
|
||||||
'Rate' => 'Taxa',
|
'Rate' => 'Taxa',
|
||||||
'Change reference currency' => 'Mudar a moeda de referência',
|
'Change reference currency' => 'Mudar a moeda de referência',
|
||||||
'Add a new currency rate' => 'Adicionar uma nova taxa para uma moeda',
|
'Add a new currency rate' => 'Adicionar uma nova taxa para uma moeda',
|
||||||
'Currency rates are used to calculate project budget.' => 'As taxas de câmbio são utilizadas para calcular o orçamento do projecto.',
|
|
||||||
'Reference currency' => 'Moeda de Referência',
|
'Reference currency' => 'Moeda de Referência',
|
||||||
'The currency rate have been added successfully.' => 'A taxa de câmbio foi adicionada com sucesso.',
|
'The currency rate have been added successfully.' => 'A taxa de câmbio foi adicionada com sucesso.',
|
||||||
'Unable to add this currency rate.' => 'Impossível adicionar essa taxa de câmbio.',
|
'Unable to add this currency rate.' => 'Impossível adicionar essa taxa de câmbio.',
|
||||||
|
@ -878,9 +826,6 @@ return array(
|
||||||
'%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 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"',
|
'%s moved the task #%d to the swimlane "%s"' => '%s moveu a tarefa n° %d no swimlane "%s"',
|
||||||
'Swimlane' => 'Swimlane',
|
'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',
|
'Gravatar' => 'Gravatar',
|
||||||
'Hipchat' => 'Hipchat',
|
'Hipchat' => 'Hipchat',
|
||||||
'Slack' => 'Slack',
|
'Slack' => 'Slack',
|
||||||
|
@ -1060,11 +1005,55 @@ return array(
|
||||||
'Gitlab Account' => 'Conta Gitlab',
|
'Gitlab Account' => 'Conta Gitlab',
|
||||||
'Link my Gitlab Account' => 'Connectar a minha Conta Gitlab',
|
'Link my Gitlab Account' => 'Connectar a minha Conta Gitlab',
|
||||||
'Unlink my Gitlab Account' => 'Desconectar a minha Conta Gitlab',
|
'Unlink my Gitlab Account' => 'Desconectar a minha Conta Gitlab',
|
||||||
// 'Documentation: %s' => '',
|
'Documentation: %s' => 'Documentação: %s',
|
||||||
// 'Switch to the Gantt chart view' => '',
|
'Switch to the Gantt chart view' => 'Mudar para vista de gráfico de Gantt',
|
||||||
// 'Reset the search/filter box' => '',
|
'Reset the search/filter box' => 'Repor caixa de procura/filtro',
|
||||||
// 'Documentation' => '',
|
'Documentation' => 'Documentação',
|
||||||
// 'Table of contents' => '',
|
'Table of contents' => 'Tabela de conteúdos',
|
||||||
// 'Gantt' => '',
|
'Gantt' => 'Gantt',
|
||||||
// 'Help with project permissions' => '',
|
'Help with project permissions' => 'Ajuda com permissões de projecto',
|
||||||
|
'Author' => 'Autor',
|
||||||
|
'Version' => 'Versão',
|
||||||
|
'Plugins' => 'Extras',
|
||||||
|
'There is no plugin loaded.' => 'Não existem extras carregados',
|
||||||
|
'Set maximum column height' => 'Definir altura máxima da coluna',
|
||||||
|
'Remove maximum column height' => 'Remover altura máxima da coluna',
|
||||||
|
'My notifications' => 'As minhas notificações',
|
||||||
|
'Custom filters' => 'Filtros personalizados',
|
||||||
|
'Your custom filter have been created successfully.' => 'O seu filtro personalizado foi criado com sucesso.',
|
||||||
|
'Unable to create your custom filter.' => 'Não foi possivel criar o seu filtro personalizado.',
|
||||||
|
'Custom filter removed successfully.' => 'Filtro personalizado removido com sucesso.',
|
||||||
|
'Unable to remove this custom filter.' => 'Não foi possivel remover este filtro personalizado.',
|
||||||
|
'Edit custom filter' => 'Editar filtro personalizado',
|
||||||
|
'Your custom filter have been updated successfully.' => 'O seu filtro personalizado foi actualizado com sucesso.',
|
||||||
|
'Unable to update custom filter.' => 'Não foi possivel actualizar o filtro personalizado.',
|
||||||
|
'Web' => 'Web',
|
||||||
|
'New attachment on task #%d: %s' => 'Novo anexo na tarefa #%d: %s',
|
||||||
|
'New comment on task #%d' => 'Novo comentário na tarefa #%d',
|
||||||
|
'Comment updated on task #%d' => 'Comentário actualizado na tarefa #%d',
|
||||||
|
'New subtask on task #%d' => 'Nova sub-tarefa na tarefa #%d',
|
||||||
|
'Subtask updated on task #%d' => 'Sub-tarefa actualizada na tarefa #%d',
|
||||||
|
'New task #%d: %s' => 'Nova tarefa #%d: %s',
|
||||||
|
'Task updated #%d' => 'Tarefa actualizada #%d',
|
||||||
|
'Task #%d closed' => 'Tarefa #%d fechada',
|
||||||
|
'Task #%d opened' => 'Tarefa #%d aberta',
|
||||||
|
'Column changed for task #%d' => 'Coluna alterada para tarefa #%d',
|
||||||
|
'New position for task #%d' => 'Nova posição para tarefa #%d',
|
||||||
|
'Swimlane changed for task #%d' => 'Swimlane alterado na tarefa #%d',
|
||||||
|
'Assignee changed on task #%d' => 'Assignado alterado na tarefa #%d',
|
||||||
|
'%d overdue tasks' => '%d tarefas em atraso',
|
||||||
|
'Task #%d is overdue' => 'Tarefa #%d está em atraso',
|
||||||
|
'No new notifications.' => 'Sem novas notificações.',
|
||||||
|
'Mark all as read' => 'Marcar tudo como lido',
|
||||||
|
'Mark as read' => 'Marcar como lido',
|
||||||
|
'Total number of tasks in this column across all swimlanes' => 'Número total de tarefas nesta coluna em todas as swimlanes',
|
||||||
|
'Collapse swimlane' => 'Colapsar swimlane',
|
||||||
|
'Expand swimlane' => 'Expandir swimlane',
|
||||||
|
'Add a new filter' => 'Adicionar um novo filtro',
|
||||||
|
'Share with all project members' => 'Partilhar com todos os membros do projecto',
|
||||||
|
'Shared' => 'Partilhado',
|
||||||
|
'Owner' => 'Dono',
|
||||||
|
'Unread notifications' => 'Notificações por ler',
|
||||||
|
'My filters' => 'Os meus filtros',
|
||||||
|
'Notification methods:' => 'Metodos de notificação:',
|
||||||
);
|
);
|
||||||
|
|
|
@ -20,15 +20,15 @@ return array(
|
||||||
'Red' => 'Красный',
|
'Red' => 'Красный',
|
||||||
'Orange' => 'Оранжевый',
|
'Orange' => 'Оранжевый',
|
||||||
'Grey' => 'Серый',
|
'Grey' => 'Серый',
|
||||||
// 'Brown' => '',
|
'Brown' => 'Коричневый',
|
||||||
// 'Deep Orange' => '',
|
'Deep Orange' => 'Темно-оранжевый',
|
||||||
// 'Dark Grey' => '',
|
'Dark Grey' => 'Темно-серый',
|
||||||
// 'Pink' => '',
|
'Pink' => 'Розовый',
|
||||||
// 'Teal' => '',
|
'Teal' => 'Бирюзовый',
|
||||||
// 'Cyan' => '',
|
'Cyan' => 'Голубой',
|
||||||
// 'Lime' => '',
|
'Lime' => 'Лимонный',
|
||||||
// 'Light Green' => '',
|
'Light Green' => 'Светло-зеленый',
|
||||||
// 'Amber' => '',
|
'Amber' => 'Янтарный',
|
||||||
'Save' => 'Сохранить',
|
'Save' => 'Сохранить',
|
||||||
'Login' => 'Вход',
|
'Login' => 'Вход',
|
||||||
'Official website:' => 'Официальный сайт:',
|
'Official website:' => 'Официальный сайт:',
|
||||||
|
@ -61,27 +61,27 @@ return array(
|
||||||
'Inactive' => 'Неактивен',
|
'Inactive' => 'Неактивен',
|
||||||
'Active' => 'Активен',
|
'Active' => 'Активен',
|
||||||
'Add this column' => 'Добавить колонку',
|
'Add this column' => 'Добавить колонку',
|
||||||
'%d tasks on the board' => 'Задач на доске - %d',
|
'%d tasks on the board' => '%d задач на доске',
|
||||||
'%d tasks in total' => 'Задач всего - %d',
|
'%d tasks in total' => 'всего %d задач',
|
||||||
'Unable to update this board.' => 'Не удалось обновить доску.',
|
'Unable to update this board.' => 'Не удалось обновить эту доску.',
|
||||||
'Edit board' => 'Изменить доски',
|
'Edit board' => 'Изменить доску',
|
||||||
'Disable' => 'Деактивировать',
|
'Disable' => 'Выключить',
|
||||||
'Enable' => 'Активировать',
|
'Enable' => 'Включить',
|
||||||
'New project' => 'Новый проект',
|
'New project' => 'Новый проект',
|
||||||
'Do you really want to remove this project: "%s"?' => 'Вы точно хотите удалить проект: « %s » ?',
|
'Do you really want to remove this project: "%s"?' => 'Вы точно хотите удалить проект: "%s"?',
|
||||||
'Remove project' => 'Удалить проект',
|
'Remove project' => 'Удалить проект',
|
||||||
'Edit the board for "%s"' => 'Изменить доску для « %s »',
|
'Edit the board for "%s"' => 'Изменить доску для "%s"',
|
||||||
'All projects' => 'Все проекты',
|
'All projects' => 'Все проекты',
|
||||||
'Change columns' => 'Изменить колонки',
|
'Change columns' => 'Изменить колонки',
|
||||||
'Add a new column' => 'Добавить новую колонку',
|
'Add a new column' => 'Добавить новую колонку',
|
||||||
'Title' => 'Название',
|
'Title' => 'Название',
|
||||||
'Nobody assigned' => 'Никто не назначен',
|
'Nobody assigned' => 'Никто не назначен',
|
||||||
'Assigned to %s' => 'Исполнитель: %s',
|
'Assigned to %s' => 'Назначено %s',
|
||||||
'Remove a column' => 'Удалить колонку',
|
'Remove a column' => 'Удалить колонку',
|
||||||
'Remove a column from a board' => 'Удалить колонку с доски',
|
'Remove a column from a board' => 'Удалить колонку с доски',
|
||||||
'Unable to remove this column.' => 'Не удалось удалить колонку.',
|
'Unable to remove this column.' => 'Не удалось удалить эту колонку.',
|
||||||
'Do you really want to remove this column: "%s"?' => 'Вы точно хотите удалить эту колонку: « %s » ?',
|
'Do you really want to remove this column: "%s"?' => 'Вы точно хотите удалить эту колонку: "%s" ?',
|
||||||
'This action will REMOVE ALL TASKS associated to this column!' => 'Вы УДАЛИТЕ ВСЕ ЗАДАЧИ находящиеся в этой колонке !',
|
'This action will REMOVE ALL TASKS associated to this column!' => 'Вы УДАЛИТЕ ВСЕ ЗАДАЧИ находящиеся в этой колонке!',
|
||||||
'Settings' => 'Настройки',
|
'Settings' => 'Настройки',
|
||||||
'Application settings' => 'Настройки приложения',
|
'Application settings' => 'Настройки приложения',
|
||||||
'Language' => 'Язык',
|
'Language' => 'Язык',
|
||||||
|
@ -100,32 +100,32 @@ return array(
|
||||||
'Create another task' => 'Создать другую задачу',
|
'Create another task' => 'Создать другую задачу',
|
||||||
'New task' => 'Новая задача',
|
'New task' => 'Новая задача',
|
||||||
'Open a task' => 'Открыть задачу',
|
'Open a task' => 'Открыть задачу',
|
||||||
'Do you really want to open this task: "%s"?' => 'Вы уверены что хотите открыть задачу: « %s » ?',
|
'Do you really want to open this task: "%s"?' => 'Вы уверены что хотите открыть задачу: "%s" ?',
|
||||||
'Back to the board' => 'Вернуться на доску',
|
'Back to the board' => 'Вернуться на доску',
|
||||||
'Created on %B %e, %Y at %k:%M %p' => 'Создано %d/%m/%Y в %H:%M',
|
'Created on %B %e, %Y at %k:%M %p' => 'Создано %B /%e /%Y в %k:%M %p',
|
||||||
'There is nobody assigned' => 'Никто не назначен',
|
'There is nobody assigned' => 'Никто не назначен',
|
||||||
'Column on the board:' => 'Колонка на доске : ',
|
'Column on the board:' => 'Колонка на доске: ',
|
||||||
'Status is open' => 'Статус - открыт',
|
'Status is open' => 'Статус - открыт',
|
||||||
'Status is closed' => 'Статус - закрыт',
|
'Status is closed' => 'Статус - закрыт',
|
||||||
'Close this task' => 'Закрыть эту задачу',
|
'Close this task' => 'Закрыть задачу',
|
||||||
'Open this task' => 'Открыть эту задачу',
|
'Open this task' => 'Открыть задачу',
|
||||||
'There is no description.' => 'Нет описания.',
|
'There is no description.' => 'Нет описания.',
|
||||||
'Add a new task' => 'Добавить новую задачу',
|
'Add a new task' => 'Добавить новую задачу',
|
||||||
'The username is required' => 'Требуется имя пользователя',
|
'The username is required' => 'Необходимо имя пользователя',
|
||||||
'The maximum length is %d characters' => 'Максимальная длина - %d знаков',
|
'The maximum length is %d characters' => 'Максимальная длина - %d знаков',
|
||||||
'The minimum length is %d characters' => 'Минимальная длина - %d знаков',
|
'The minimum length is %d characters' => 'Минимальная длина - %d знаков',
|
||||||
'The password is required' => 'Требуется пароль',
|
'The password is required' => 'Необходим пароль',
|
||||||
'This value must be an integer' => 'Это значение должно быть целым',
|
'This value must be an integer' => 'Это значение должно быть целым числом',
|
||||||
'The username must be unique' => 'Требуется уникальное имя пользователя',
|
'The username must be unique' => 'Имя пользователя должно быть уникально',
|
||||||
'The user id is required' => 'Требуется ID пользователя',
|
'The user id is required' => 'Необходим ID пользователя',
|
||||||
'Passwords don\'t match' => 'Пароли не совпадают',
|
'Passwords don\'t match' => 'Пароли не совпадают',
|
||||||
'The confirmation is required' => 'Требуется подтверждение',
|
'The confirmation is required' => 'Необходимо подтверждение',
|
||||||
'The project is required' => 'Требуется проект',
|
'The project is required' => 'Необъодимо указать проект',
|
||||||
'The id is required' => 'Требуется ID',
|
'The id is required' => 'Необходим ID',
|
||||||
'The project id is required' => 'Требуется ID проекта',
|
'The project id is required' => 'Необходим ID проекта',
|
||||||
'The project name is required' => 'Требуется имя проекта',
|
'The project name is required' => 'Необходимо имя проекта',
|
||||||
'This project must be unique' => 'Проект должен быть уникальным',
|
'This project must be unique' => 'Проект должен быть уникальным',
|
||||||
'The title is required' => 'Требуется заголовок',
|
'The title is required' => 'Необходим заголовок',
|
||||||
'Settings saved successfully.' => 'Параметры успешно сохранены.',
|
'Settings saved successfully.' => 'Параметры успешно сохранены.',
|
||||||
'Unable to save your settings.' => 'Невозможно сохранить параметры.',
|
'Unable to save your settings.' => 'Невозможно сохранить параметры.',
|
||||||
'Database optimization done.' => 'База данных оптимизирована.',
|
'Database optimization done.' => 'База данных оптимизирована.',
|
||||||
|
@ -157,7 +157,7 @@ return array(
|
||||||
'Ready' => 'Готовые',
|
'Ready' => 'Готовые',
|
||||||
'Backlog' => 'Ожидающие',
|
'Backlog' => 'Ожидающие',
|
||||||
'Work in progress' => 'В процессе',
|
'Work in progress' => 'В процессе',
|
||||||
'Done' => 'Выполнена',
|
'Done' => 'Выполнено',
|
||||||
'Application version:' => 'Версия приложения:',
|
'Application version:' => 'Версия приложения:',
|
||||||
'Completed on %B %e, %Y at %k:%M %p' => 'Завершен %d/%m/%Y в %H:%M',
|
'Completed on %B %e, %Y at %k:%M %p' => 'Завершен %d/%m/%Y в %H:%M',
|
||||||
'%B %e, %Y at %k:%M %p' => '%d/%m/%Y в %H:%M',
|
'%B %e, %Y at %k:%M %p' => '%d/%m/%Y в %H:%M',
|
||||||
|
@ -193,9 +193,9 @@ return array(
|
||||||
'Edit this task' => 'Изменить задачу',
|
'Edit this task' => 'Изменить задачу',
|
||||||
'Due Date' => 'Сделать до',
|
'Due Date' => 'Сделать до',
|
||||||
'Invalid date' => 'Неверная дата',
|
'Invalid date' => 'Неверная дата',
|
||||||
'Must be done before %B %e, %Y' => 'Должно быть сделано до %d/%m/%Y',
|
'Must be done before %B %e, %Y' => 'Должно быть сделано до %B %e %Y',
|
||||||
'%B %e, %Y' => '%d/%m/%Y',
|
'%B %e, %Y' => '%B, %e, %Y',
|
||||||
// '%b %e, %Y' => '',
|
'%b %e, %Y' => '%b %e, %Y',
|
||||||
'Automatic actions' => 'Автоматические действия',
|
'Automatic actions' => 'Автоматические действия',
|
||||||
'Your automatic action have been created successfully.' => 'Автоматика успешно настроена.',
|
'Your automatic action have been created successfully.' => 'Автоматика успешно настроена.',
|
||||||
'Unable to create your automatic action.' => 'Не удалось создать автоматизированное действие.',
|
'Unable to create your automatic action.' => 'Не удалось создать автоматизированное действие.',
|
||||||
|
@ -263,10 +263,10 @@ return array(
|
||||||
'%d comments' => '%d комментариев',
|
'%d comments' => '%d комментариев',
|
||||||
'%d comment' => '%d комментарий',
|
'%d comment' => '%d комментарий',
|
||||||
'Email address invalid' => 'Некорректный e-mail адрес',
|
'Email address invalid' => 'Некорректный e-mail адрес',
|
||||||
// 'Your external account is not linked anymore to your profile.' => '',
|
'Your external account is not linked anymore to your profile.' => 'Ваш внешний аккаунт больше не связан с Вашим профилем.',
|
||||||
// 'Unable to unlink your external account.' => '',
|
'Unable to unlink your external account.' => 'Не удалось отвязать Ваш внешний аккаунт.',
|
||||||
// 'External authentication failed' => '',
|
'External authentication failed' => 'Внешняя авторизация не удалась',
|
||||||
// 'Your external account is linked to your profile successfully.' => '',
|
'Your external account is linked to your profile successfully.' => 'Ваш внешний аккаунт успешно подключен к профилю.',
|
||||||
'Email' => 'E-mail',
|
'Email' => 'E-mail',
|
||||||
'Link my Google Account' => 'Привязать мой профиль к Google',
|
'Link my Google Account' => 'Привязать мой профиль к Google',
|
||||||
'Unlink my Google Account' => 'Отвязать мой профиль от Google',
|
'Unlink my Google Account' => 'Отвязать мой профиль от Google',
|
||||||
|
@ -310,7 +310,7 @@ return array(
|
||||||
'Edit a comment' => 'Изменить комментарий',
|
'Edit a comment' => 'Изменить комментарий',
|
||||||
'Summary' => 'Сводка',
|
'Summary' => 'Сводка',
|
||||||
'Time tracking' => 'Отслеживание времени',
|
'Time tracking' => 'Отслеживание времени',
|
||||||
'Estimate:' => 'Приблизительно:',
|
'Estimate:' => 'Запланировано:',
|
||||||
'Spent:' => 'Затрачено:',
|
'Spent:' => 'Затрачено:',
|
||||||
'Do you really want to remove this sub-task?' => 'Вы точно хотите удалить подзадачу?',
|
'Do you really want to remove this sub-task?' => 'Вы точно хотите удалить подзадачу?',
|
||||||
'Remaining:' => 'Осталось:',
|
'Remaining:' => 'Осталось:',
|
||||||
|
@ -319,7 +319,7 @@ return array(
|
||||||
'estimated' => 'расчетное',
|
'estimated' => 'расчетное',
|
||||||
'Sub-Tasks' => 'Подзадачи',
|
'Sub-Tasks' => 'Подзадачи',
|
||||||
'Add a sub-task' => 'Добавить подзадачу',
|
'Add a sub-task' => 'Добавить подзадачу',
|
||||||
'Original estimate' => 'Первичная оценка',
|
'Original estimate' => 'Запланировано',
|
||||||
'Create another sub-task' => 'Создать другую подзадачу',
|
'Create another sub-task' => 'Создать другую подзадачу',
|
||||||
'Time spent' => 'Времени затрачено',
|
'Time spent' => 'Времени затрачено',
|
||||||
'Edit a sub-task' => 'Изменить подзадачу',
|
'Edit a sub-task' => 'Изменить подзадачу',
|
||||||
|
@ -395,8 +395,6 @@ return array(
|
||||||
'Remote' => 'Удаленный',
|
'Remote' => 'Удаленный',
|
||||||
'Enabled' => 'Включен',
|
'Enabled' => 'Включен',
|
||||||
'Disabled' => 'Выключены',
|
'Disabled' => 'Выключены',
|
||||||
'Google account linked' => 'Профиль Google связан',
|
|
||||||
'Github account linked' => 'Профиль Github связан',
|
|
||||||
'Username:' => 'Имя пользователя:',
|
'Username:' => 'Имя пользователя:',
|
||||||
'Name:' => 'Имя:',
|
'Name:' => 'Имя:',
|
||||||
'Email:' => 'E-mail:',
|
'Email:' => 'E-mail:',
|
||||||
|
@ -487,11 +485,11 @@ return array(
|
||||||
'This project is private' => 'Это проект с ограниченным доступом',
|
'This project is private' => 'Это проект с ограниченным доступом',
|
||||||
'Type here to create a new sub-task' => 'Печатайте сюда чтобы создать подзадачу',
|
'Type here to create a new sub-task' => 'Печатайте сюда чтобы создать подзадачу',
|
||||||
'Add' => 'Добавить',
|
'Add' => 'Добавить',
|
||||||
'Estimated time: %s hours' => 'Планируемое время: %s часов',
|
'Estimated time: %s hours' => 'Запланировано: %s часов',
|
||||||
'Time spent: %s hours' => 'Потрачено времени: %s часов',
|
'Time spent: %s hours' => 'Потрачено времени: %s часов',
|
||||||
'Started on %B %e, %Y' => 'Начато %B %e, %Y',
|
'Started on %B %e, %Y' => 'Начато %B %e, %Y',
|
||||||
'Start date' => 'Дата начала',
|
'Start date' => 'Дата начала',
|
||||||
'Time estimated' => 'Планируемое время',
|
'Time estimated' => 'Запланировано',
|
||||||
'There is nothing assigned to you.' => 'Вам ничего не назначено',
|
'There is nothing assigned to you.' => 'Вам ничего не назначено',
|
||||||
'My tasks' => 'Мои задачи',
|
'My tasks' => 'Мои задачи',
|
||||||
'Activity stream' => 'Текущая активность',
|
'Activity stream' => 'Текущая активность',
|
||||||
|
@ -522,7 +520,7 @@ return array(
|
||||||
'User repartition for "%s"' => 'Перераспределение пользователей для "%s"',
|
'User repartition for "%s"' => 'Перераспределение пользователей для "%s"',
|
||||||
'Clone this project' => 'Клонировать проект',
|
'Clone this project' => 'Клонировать проект',
|
||||||
'Column removed successfully.' => 'Колонка успешно удалена.',
|
'Column removed successfully.' => 'Колонка успешно удалена.',
|
||||||
// 'Github Issue' => '',
|
'Github Issue' => 'Вопрос на Github',
|
||||||
'Not enough data to show the graph.' => 'Недостаточно данных, чтобы показать график.',
|
'Not enough data to show the graph.' => 'Недостаточно данных, чтобы показать график.',
|
||||||
'Previous' => 'Предыдущий',
|
'Previous' => 'Предыдущий',
|
||||||
'The id must be an integer' => 'Этот id должен быть целочисленным',
|
'The id must be an integer' => 'Этот id должен быть целочисленным',
|
||||||
|
@ -593,7 +591,7 @@ return array(
|
||||||
'All columns' => 'Все колонки',
|
'All columns' => 'Все колонки',
|
||||||
'Calendar' => 'Календарь',
|
'Calendar' => 'Календарь',
|
||||||
'Next' => 'Следующий',
|
'Next' => 'Следующий',
|
||||||
// '#%d' => '',
|
'#%d' => '#%d',
|
||||||
'All swimlanes' => 'Все дорожки',
|
'All swimlanes' => 'Все дорожки',
|
||||||
'All colors' => 'Все цвета',
|
'All colors' => 'Все цвета',
|
||||||
'All status' => 'Все статусы',
|
'All status' => 'Все статусы',
|
||||||
|
@ -608,7 +606,7 @@ return array(
|
||||||
'Time Tracking' => 'Учет времени',
|
'Time Tracking' => 'Учет времени',
|
||||||
'You already have one subtask in progress' => 'У вас уже есть одна задача в разработке',
|
'You already have one subtask in progress' => 'У вас уже есть одна задача в разработке',
|
||||||
'Which parts of the project do you want to duplicate?' => 'Какие части проекта должны быть дублированы?',
|
'Which parts of the project do you want to duplicate?' => 'Какие части проекта должны быть дублированы?',
|
||||||
// 'Disallow login form' => '',
|
'Disallow login form' => 'Запретить форму входа',
|
||||||
// 'Bitbucket commit received' => '',
|
// 'Bitbucket commit received' => '',
|
||||||
'Bitbucket webhooks' => 'BitBucket webhooks',
|
'Bitbucket webhooks' => 'BitBucket webhooks',
|
||||||
'Help on Bitbucket webhooks' => 'Помощь по BitBucket webhooks',
|
'Help on Bitbucket webhooks' => 'Помощь по BitBucket webhooks',
|
||||||
|
@ -616,7 +614,7 @@ return array(
|
||||||
'End' => 'Конец',
|
'End' => 'Конец',
|
||||||
'Task age in days' => 'Возраст задачи в днях',
|
'Task age in days' => 'Возраст задачи в днях',
|
||||||
'Days in this column' => 'Дней в этой колонке',
|
'Days in this column' => 'Дней в этой колонке',
|
||||||
// '%dd' => '',
|
'%dd' => '%dd',
|
||||||
'Add a link' => 'Добавить ссылку на другие задачи',
|
'Add a link' => 'Добавить ссылку на другие задачи',
|
||||||
'Add a new link' => 'Добавление новой ссылки',
|
'Add a new link' => 'Добавление новой ссылки',
|
||||||
'Do you really want to remove this link: "%s"?' => 'Вы уверены что хотите удалить ссылку: "%s"?',
|
'Do you really want to remove this link: "%s"?' => 'Вы уверены что хотите удалить ссылку: "%s"?',
|
||||||
|
@ -638,21 +636,21 @@ return array(
|
||||||
'Unable to create your link.' => 'Не удается создать эту ссылку.',
|
'Unable to create your link.' => 'Не удается создать эту ссылку.',
|
||||||
'Unable to update your link.' => 'Не удается обновить эту ссылку.',
|
'Unable to update your link.' => 'Не удается обновить эту ссылку.',
|
||||||
'Unable to remove this link.' => 'Не удается удалить эту ссылку.',
|
'Unable to remove this link.' => 'Не удается удалить эту ссылку.',
|
||||||
'relates to' => 'связана с',
|
'relates to' => 'относится к',
|
||||||
'blocks' => 'блокирует',
|
'blocks' => 'блокирована',
|
||||||
'is blocked by' => 'заблокирована в',
|
'is blocked by' => 'блокирует',
|
||||||
'duplicates' => 'дублирует',
|
'duplicates' => 'дублирована',
|
||||||
'is duplicated by' => 'дублирована в',
|
'is duplicated by' => 'дублирует',
|
||||||
'is a child of' => 'наследник',
|
'is a child of' => 'является продолжением',
|
||||||
'is a parent of' => 'родитель',
|
'is a parent of' => 'является началом для',
|
||||||
'targets milestone' => 'часть этапа',
|
'targets milestone' => 'часть вехи',
|
||||||
'is a milestone of' => 'является частью этапа',
|
'is a milestone of' => 'является вехой для',
|
||||||
'fixes' => 'исправляет',
|
'fixes' => 'исправлено',
|
||||||
'is fixed by' => 'исправлено в',
|
'is fixed by' => 'исправляет',
|
||||||
'This task' => 'Эта задача',
|
'This task' => 'Эта задача',
|
||||||
'<1h' => '<1ч',
|
'<1h' => '<1ч',
|
||||||
// '%dh' => '',
|
'%dh' => '%dh',
|
||||||
// '%b %e' => '',
|
'%b %e' => '%b %e',
|
||||||
'Expand tasks' => 'Развернуть задачи',
|
'Expand tasks' => 'Развернуть задачи',
|
||||||
'Collapse tasks' => 'Свернуть задачи',
|
'Collapse tasks' => 'Свернуть задачи',
|
||||||
'Expand/collapse tasks' => 'Развернуть/свернуть задачи',
|
'Expand/collapse tasks' => 'Развернуть/свернуть задачи',
|
||||||
|
@ -667,75 +665,26 @@ return array(
|
||||||
'Horizontal scrolling' => 'Широкий вид',
|
'Horizontal scrolling' => 'Широкий вид',
|
||||||
'Compact/wide view' => 'Компактный/широкий вид',
|
'Compact/wide view' => 'Компактный/широкий вид',
|
||||||
'No results match:' => 'Отсутствуют результаты:',
|
'No results match:' => 'Отсутствуют результаты:',
|
||||||
'Remove hourly rate' => 'Удалить почасовую ставку',
|
|
||||||
'Do you really want to remove this hourly rate?' => 'Вы действительно хотите удалить эту почасовую ставку?',
|
|
||||||
'Hourly rates' => 'Почасовые ставки',
|
|
||||||
'Hourly rate' => 'Почасовая ставка',
|
|
||||||
'Currency' => 'Валюта',
|
'Currency' => 'Валюта',
|
||||||
'Effective date' => 'Дата вступления в силу',
|
|
||||||
'Add new rate' => 'Добавить новый показатель',
|
|
||||||
'Rate removed successfully.' => 'Показатель успешно удален.',
|
|
||||||
'Unable to remove this rate.' => 'Не удается удалить этот показатель.',
|
|
||||||
'Unable to save the hourly rate.' => 'Не удается сохранить почасовую ставку.',
|
|
||||||
'Hourly rate created successfully.' => 'Почасовая ставка успешно создана.',
|
|
||||||
'Start time' => 'Время начала',
|
|
||||||
'End time' => 'Время завершения',
|
|
||||||
'Comment' => 'Комментарий',
|
|
||||||
'All day' => 'Весь день',
|
|
||||||
'Day' => 'День',
|
|
||||||
'Manage timetable' => 'Управление графиками',
|
|
||||||
'Overtime timetable' => 'График сверхурочных',
|
|
||||||
'Time off timetable' => 'Время в графике',
|
|
||||||
'Timetable' => 'График',
|
|
||||||
'Work timetable' => 'Work timetable',
|
|
||||||
'Week timetable' => 'График на неделю',
|
|
||||||
'Day timetable' => 'График на день',
|
|
||||||
'From' => 'От кого',
|
|
||||||
'To' => 'Кому',
|
|
||||||
'Time slot created successfully.' => 'Временной интервал успешно создан.',
|
|
||||||
'Unable to save this time slot.' => 'Невозможно сохранить этот временной интервал.',
|
|
||||||
'Time slot removed successfully.' => 'Временной интервал успешно удален.',
|
|
||||||
'Unable to remove this time slot.' => 'Не удается удалить этот временной интервал.',
|
|
||||||
'Do you really want to remove this time slot?' => 'Вы действительно хотите удалить этот период времени?',
|
|
||||||
'Remove time slot' => 'Удалить новый интервал времени',
|
|
||||||
'Add new time slot' => 'Добавить новый интервал времени',
|
|
||||||
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
|
|
||||||
'Files' => 'Файлы',
|
'Files' => 'Файлы',
|
||||||
'Images' => 'Изображения',
|
'Images' => 'Изображения',
|
||||||
'Private project' => 'Приватный проект',
|
'Private project' => 'Приватный проект',
|
||||||
'Amount' => 'Количество',
|
|
||||||
'AUD - Australian Dollar' => 'AUD - Австралийский доллар',
|
'AUD - Australian Dollar' => 'AUD - Австралийский доллар',
|
||||||
'Budget' => 'Бюджет',
|
|
||||||
'Budget line' => 'Статья бюджета',
|
|
||||||
'Budget line removed successfully.' => 'Бюджетная статья успешно удалена.',
|
|
||||||
'Budget lines' => 'Статьи бюджета',
|
|
||||||
'CAD - Canadian Dollar' => 'CAD - Канадский доллар',
|
'CAD - Canadian Dollar' => 'CAD - Канадский доллар',
|
||||||
'CHF - Swiss Francs' => 'CHF - Швейцарский Франк',
|
'CHF - Swiss Francs' => 'CHF - Швейцарский Франк',
|
||||||
'Cost' => 'Стоимость',
|
|
||||||
'Cost breakdown' => 'Детализация затрат',
|
|
||||||
'Custom Stylesheet' => 'Пользовательский стиль',
|
'Custom Stylesheet' => 'Пользовательский стиль',
|
||||||
'download' => 'загрузить',
|
'download' => 'загрузить',
|
||||||
'Do you really want to remove this budget line?' => 'Вы действительно хотите удалить эту статью бюджета?',
|
|
||||||
'EUR - Euro' => 'EUR - Евро',
|
'EUR - Euro' => 'EUR - Евро',
|
||||||
'Expenses' => 'Расходы',
|
|
||||||
'GBP - British Pound' => 'GBP - Британский фунт',
|
'GBP - British Pound' => 'GBP - Британский фунт',
|
||||||
'INR - Indian Rupee' => 'INR - Индийский рупий',
|
'INR - Indian Rupee' => 'INR - Индийский рупий',
|
||||||
'JPY - Japanese Yen' => 'JPY - Японскай йена',
|
'JPY - Japanese Yen' => 'JPY - Японскай йена',
|
||||||
'New budget line' => 'Новая статья бюджета',
|
|
||||||
'NZD - New Zealand Dollar' => 'NZD - Новозеландский доллар',
|
'NZD - New Zealand Dollar' => 'NZD - Новозеландский доллар',
|
||||||
'Remove a budget line' => 'Удалить строку в бюджете',
|
|
||||||
'Remove budget line' => 'Удалить статью бюджета',
|
|
||||||
'RSD - Serbian dinar' => 'RSD - Сербский динар',
|
'RSD - Serbian dinar' => 'RSD - Сербский динар',
|
||||||
'The budget line have been created successfully.' => 'Статья бюджета успешно создана.',
|
|
||||||
'Unable to create the budget line.' => 'Не удается создать эту статью бюджета.',
|
|
||||||
'Unable to remove this budget line.' => 'Не удается удалить эту статью бюджета.',
|
|
||||||
'USD - US Dollar' => 'USD - доллар США',
|
'USD - US Dollar' => 'USD - доллар США',
|
||||||
'Remaining' => 'Прочее',
|
|
||||||
'Destination column' => 'Колонка назначения',
|
'Destination column' => 'Колонка назначения',
|
||||||
'Move the task to another column when assigned to a user' => 'Переместить задачу в другую колонку, когда она назначена пользователю',
|
'Move the task to another column when assigned to a user' => 'Переместить задачу в другую колонку, когда она назначена пользователю',
|
||||||
'Move the task to another column when assignee is cleared' => 'Переместить задачу в другую колонку, когда назначение снято ',
|
'Move the task to another column when assignee is cleared' => 'Переместить задачу в другую колонку, когда назначение снято ',
|
||||||
'Source column' => 'Исходная колонка',
|
'Source column' => 'Исходная колонка',
|
||||||
'Show subtask estimates (forecast of future work)' => 'Показать оценку подзадач (прогноз будущей работы)',
|
|
||||||
'Transitions' => 'Перемещения',
|
'Transitions' => 'Перемещения',
|
||||||
'Executer' => 'Исполнитель',
|
'Executer' => 'Исполнитель',
|
||||||
'Time spent in the column' => 'Время проведенное в колонке',
|
'Time spent in the column' => 'Время проведенное в колонке',
|
||||||
|
@ -745,8 +694,7 @@ return array(
|
||||||
'Currency rates' => 'Курсы валют',
|
'Currency rates' => 'Курсы валют',
|
||||||
'Rate' => 'Курс',
|
'Rate' => 'Курс',
|
||||||
'Change reference currency' => 'Изменить справочник валют',
|
'Change reference currency' => 'Изменить справочник валют',
|
||||||
'Add a new currency rate' => 'Add a new currency rate',
|
'Add a new currency rate' => 'Добавить новый валютный курс',
|
||||||
'Currency rates are used to calculate project budget.' => 'Курсы валют используются для расчета бюджета проекта.',
|
|
||||||
'Reference currency' => 'Справочник валют',
|
'Reference currency' => 'Справочник валют',
|
||||||
'The currency rate have been added successfully.' => 'Курс валюты был успешно добавлен.',
|
'The currency rate have been added successfully.' => 'Курс валюты был успешно добавлен.',
|
||||||
'Unable to add this currency rate.' => 'Невозможно добавить этот курс валюты.',
|
'Unable to add this currency rate.' => 'Невозможно добавить этот курс валюты.',
|
||||||
|
@ -774,8 +722,8 @@ return array(
|
||||||
'Test your device' => 'Проверьте свое устройство',
|
'Test your device' => 'Проверьте свое устройство',
|
||||||
'Assign a color when the task is moved to a specific column' => 'Назначить цвет, когда задача перемещается в определенную колонку',
|
'Assign a color when the task is moved to a specific column' => 'Назначить цвет, когда задача перемещается в определенную колонку',
|
||||||
'%s via Kanboard' => '%s через Канборд',
|
'%s via Kanboard' => '%s через Канборд',
|
||||||
// 'uploaded by: %s' => '',
|
'uploaded by: %s' => 'загружено: %s',
|
||||||
// 'uploaded on: %s' => '',
|
'uploaded on: %s' => 'загружено в: %s',
|
||||||
'size: %s' => 'размер: %s',
|
'size: %s' => 'размер: %s',
|
||||||
'Burndown chart for "%s"' => 'Диаграмма сгорания для « %s »',
|
'Burndown chart for "%s"' => 'Диаграмма сгорания для « %s »',
|
||||||
'Burndown chart' => 'Диаграмма сгорания',
|
'Burndown chart' => 'Диаграмма сгорания',
|
||||||
|
@ -805,7 +753,7 @@ return array(
|
||||||
'The identifier must be unique' => 'Идентификатор должен быть уникальным',
|
'The identifier must be unique' => 'Идентификатор должен быть уникальным',
|
||||||
'This linked task id doesn\'t exists' => 'Этот ID звязанной задачи не существует',
|
'This linked task id doesn\'t exists' => 'Этот ID звязанной задачи не существует',
|
||||||
'This value must be alphanumeric' => 'Это значение должно быть буквенно-цифровым',
|
'This value must be alphanumeric' => 'Это значение должно быть буквенно-цифровым',
|
||||||
'Edit recurrence' => 'Завершить повторение',
|
'Edit recurrence' => 'Редактировать повторы',
|
||||||
'Generate recurrent task' => 'Создать повторяющуюся задачу',
|
'Generate recurrent task' => 'Создать повторяющуюся задачу',
|
||||||
'Trigger to generate recurrent task' => 'Триггер для генерации периодической задачи',
|
'Trigger to generate recurrent task' => 'Триггер для генерации периодической задачи',
|
||||||
'Factor to calculate new due date' => 'Коэффициент для рассчета новой даты',
|
'Factor to calculate new due date' => 'Коэффициент для рассчета новой даты',
|
||||||
|
@ -850,10 +798,10 @@ return array(
|
||||||
'Two factor authentication disabled' => 'Двухфакторная аутентификация отключена',
|
'Two factor authentication disabled' => 'Двухфакторная аутентификация отключена',
|
||||||
'Two factor authentication enabled' => 'Включена двухфакторная аутентификация',
|
'Two factor authentication enabled' => 'Включена двухфакторная аутентификация',
|
||||||
'Unable to update this user.' => 'Не удается обновить этого пользователя.',
|
'Unable to update this user.' => 'Не удается обновить этого пользователя.',
|
||||||
'There is no user management for private projects.' => 'Там нет управления пользователя для частных проектов',
|
'There is no user management for private projects.' => 'Для приватных проектов управление пользователями не предусмотрено.',
|
||||||
// 'User that will receive the email' => '',
|
'User that will receive the email' => 'Пользователь, который будет получать e-mail',
|
||||||
// 'Email subject' => '',
|
'Email subject' => 'Тема e-mail',
|
||||||
// 'Date' => '',
|
'Date' => 'Дата',
|
||||||
// 'By @%s on Bitbucket' => '',
|
// 'By @%s on Bitbucket' => '',
|
||||||
// 'Bitbucket Issue' => '',
|
// 'Bitbucket Issue' => '',
|
||||||
// 'Commit made by @%s on Bitbucket' => '',
|
// 'Commit made by @%s on Bitbucket' => '',
|
||||||
|
@ -869,202 +817,243 @@ return array(
|
||||||
// 'Bitbucket issue reopened' => '',
|
// 'Bitbucket issue reopened' => '',
|
||||||
// 'Bitbucket issue assignee change' => '',
|
// 'Bitbucket issue assignee change' => '',
|
||||||
// 'Bitbucket issue comment created' => '',
|
// 'Bitbucket issue comment created' => '',
|
||||||
// 'Column change' => '',
|
'Column change' => 'Изменение колонки',
|
||||||
// 'Position change' => '',
|
'Position change' => 'Позиция изменена',
|
||||||
// 'Swimlane change' => '',
|
'Swimlane change' => 'Дорожка изменена',
|
||||||
// 'Assignee change' => '',
|
// 'Assignee change' => '',
|
||||||
// '[%s] Overdue tasks' => '',
|
'[%s] Overdue tasks' => '[%s] просроченные задачи',
|
||||||
// 'Notification' => '',
|
'Notification' => 'Уведомления',
|
||||||
// '%s moved the task #%d to the first swimlane' => '',
|
'%s moved the task #%d to the first swimlane' => '%s задач перемещено #%d в первой дорожке',
|
||||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
'%s moved the task #%d to the swimlane "%s"' => '%s задач перемещено #%d в дорожке "%s"',
|
||||||
// 'Swimlane' => '',
|
'Swimlane' => 'Дорожки',
|
||||||
// 'Budget overview' => '',
|
'Gravatar' => 'Граватар',
|
||||||
// 'Type' => '',
|
'Hipchat' => 'Hipchat',
|
||||||
// 'There is not enough data to show something.' => '',
|
'Slack' => 'Slack',
|
||||||
// 'Gravatar' => '',
|
|
||||||
// 'Hipchat' => '',
|
|
||||||
// 'Slack' => '',
|
|
||||||
// '%s moved the task %s to the first swimlane' => '',
|
// '%s moved the task %s to the first swimlane' => '',
|
||||||
// '%s moved the task %s to the swimlane "%s"' => '',
|
// '%s moved the task %s to the swimlane "%s"' => '',
|
||||||
// 'This report contains all subtasks information for the given date range.' => '',
|
'This report contains all subtasks information for the given date range.' => 'Этот отчет содержит всю информацию подзадач в заданном диапазоне дат.',
|
||||||
// 'This report contains all tasks information for the given date range.' => '',
|
'This report contains all tasks information for the given date range.' => 'Этот отчет содержит всю информацию для задачи в заданном диапазоне дат.',
|
||||||
// 'Project activities for %s' => '',
|
'Project activities for %s' => 'Активность проекта для %s',
|
||||||
// 'view the board on Kanboard' => '',
|
// 'view the board on Kanboard' => '',
|
||||||
// 'The task have been moved to the first swimlane' => '',
|
'The task have been moved to the first swimlane' => 'Эта задача была перемещена в первую дорожку',
|
||||||
// 'The task have been moved to another swimlane:' => '',
|
'The task have been moved to another swimlane:' => 'Эта задача была перемещена в другую дорожку:',
|
||||||
// 'Overdue tasks for the project "%s"' => '',
|
'Overdue tasks for the project "%s"' => 'Просроченные задачи для проекта "%s"',
|
||||||
// 'New title: %s' => '',
|
'New title: %s' => 'Новый заголовок: %s',
|
||||||
// 'The task is not assigned anymore' => '',
|
'The task is not assigned anymore' => 'Задача больше не назначена',
|
||||||
// 'New assignee: %s' => '',
|
// 'New assignee: %s' => '',
|
||||||
// 'There is no category now' => '',
|
'There is no category now' => 'В настоящее время здесь нет категорий',
|
||||||
// 'New category: %s' => '',
|
'New category: %s' => 'Новая категория: %s',
|
||||||
// 'New color: %s' => '',
|
'New color: %s' => 'Новый цвет: %s',
|
||||||
// 'New complexity: %d' => '',
|
'New complexity: %d' => 'Новая сложность: %d',
|
||||||
// 'The due date have been removed' => '',
|
'The due date have been removed' => 'Дата завершения была удалена',
|
||||||
// 'There is no description anymore' => '',
|
'There is no description anymore' => 'Здесь больше нет описания',
|
||||||
// 'Recurrence settings have been modified' => '',
|
'Recurrence settings have been modified' => 'Настройки повтора были изменены',
|
||||||
// 'Time spent changed: %sh' => '',
|
'Time spent changed: %sh' => 'Изменение количества затраченного времени: %sh',
|
||||||
// 'Time estimated changed: %sh' => '',
|
'Time estimated changed: %sh' => 'Ожидаемый срок изменен: %sh',
|
||||||
// 'The field "%s" have been updated' => '',
|
'The field "%s" have been updated' => 'Поле "%s" ,было изменено',
|
||||||
// 'The description have been modified' => '',
|
'The description have been modified' => 'Описание было изменено',
|
||||||
// 'Do you really want to close the task "%s" as well as all subtasks?' => '',
|
'Do you really want to close the task "%s" as well as all subtasks?' => 'Вы действительно хотите закрыть задачу "%s", а также все подзадачи?',
|
||||||
// 'Swimlane: %s' => '',
|
'Swimlane: %s' => 'Дорожка: %s',
|
||||||
// 'I want to receive notifications for:' => '',
|
'I want to receive notifications for:' => 'Я хочу получать уведомления для:',
|
||||||
// 'All tasks' => '',
|
'All tasks' => 'Все задачи',
|
||||||
// 'Only for tasks assigned to me' => '',
|
'Only for tasks assigned to me' => 'Только для задач, назначенных на меня',
|
||||||
// 'Only for tasks created by me' => '',
|
'Only for tasks created by me' => 'Только для задач, созданных мной',
|
||||||
// 'Only for tasks created by me and assigned to me' => '',
|
'Only for tasks created by me and assigned to me' => 'Только для задач, созданных мной и назначенных мной',
|
||||||
// '%A' => '',
|
'%A' => '%A',
|
||||||
// '%b %e, %Y, %k:%M %p' => '',
|
'%b %e, %Y, %k:%M %p' => '%b %e, %Y, %k:%M %p',
|
||||||
// 'New due date: %B %e, %Y' => '',
|
'New due date: %B %e, %Y' => 'Новая дата завершения: %B %e, %Y',
|
||||||
// 'Start date changed: %B %e, %Y' => '',
|
'Start date changed: %B %e, %Y' => 'Изменить дату начала: %B %e, %Y',
|
||||||
// '%k:%M %p' => '',
|
'%k:%M %p' => '%k:%M %p',
|
||||||
// '%%Y-%%m-%%d' => '',
|
'%%Y-%%m-%%d' => '%%Y-%%m-%%d',
|
||||||
// 'Total for all columns' => '',
|
'Total for all columns' => 'Суммарно для всех колонок',
|
||||||
// 'You need at least 2 days of data to show the chart.' => '',
|
'You need at least 2 days of data to show the chart.' => 'Для отображения диаграммы нужно по крайней мере 2 дня.',
|
||||||
// '<15m' => '',
|
'<15m' => '<15м',
|
||||||
// '<30m' => '',
|
'<30m' => '<30м',
|
||||||
// 'Stop timer' => '',
|
'Stop timer' => 'Остановить таймер',
|
||||||
// 'Start timer' => '',
|
'Start timer' => 'Запустить таймер',
|
||||||
// 'Add project member' => '',
|
'Add project member' => 'Добавить номер проекта',
|
||||||
// 'Enable notifications' => '',
|
'Enable notifications' => 'Отключить уведомления',
|
||||||
// 'My activity stream' => '',
|
'My activity stream' => 'Лента моей активности',
|
||||||
// 'My calendar' => '',
|
'My calendar' => 'Мой календарь',
|
||||||
// 'Search tasks' => '',
|
'Search tasks' => 'Поиск задачи',
|
||||||
// 'Back to the calendar' => '',
|
'Back to the calendar' => 'Вернуться в календарь',
|
||||||
// 'Filters' => '',
|
'Filters' => 'Фильтры',
|
||||||
// 'Reset filters' => '',
|
'Reset filters' => 'Сбросить фильтры',
|
||||||
// 'My tasks due tomorrow' => '',
|
'My tasks due tomorrow' => 'Мои задачи на завтра',
|
||||||
// 'Tasks due today' => '',
|
'Tasks due today' => 'Задачи, завершающиеся сегодня',
|
||||||
// 'Tasks due tomorrow' => '',
|
'Tasks due tomorrow' => 'Задачи, завершающиеся завтра',
|
||||||
// 'Tasks due yesterday' => '',
|
'Tasks due yesterday' => 'Задачи, завершившиеся вчера',
|
||||||
// 'Closed tasks' => '',
|
'Closed tasks' => 'Закрытые задачи',
|
||||||
// 'Open tasks' => '',
|
'Open tasks' => 'Открытые задачи',
|
||||||
// 'Not assigned' => '',
|
'Not assigned' => 'Не назначенные',
|
||||||
// 'View advanced search syntax' => '',
|
'View advanced search syntax' => 'Просмотр расширенного синтаксиса поиска',
|
||||||
// 'Overview' => '',
|
'Overview' => 'Обзор',
|
||||||
// '%b %e %Y' => '',
|
'%b %e %Y' => '%b %e %Y',
|
||||||
// 'Board/Calendar/List view' => '',
|
'Board/Calendar/List view' => 'Просмотр Доска/Календарь/Список',
|
||||||
// 'Switch to the board view' => '',
|
'Switch to the board view' => 'Переключиться в режим доски',
|
||||||
// 'Switch to the calendar view' => '',
|
'Switch to the calendar view' => 'Переключиться в режим календаря',
|
||||||
// 'Switch to the list view' => '',
|
'Switch to the list view' => 'Переключиться в режим списка',
|
||||||
// 'Go to the search/filter box' => '',
|
'Go to the search/filter box' => 'Перейти в поиск/фильтр',
|
||||||
// 'There is no activity yet.' => '',
|
'There is no activity yet.' => 'Активности еще не было',
|
||||||
// 'No tasks found.' => '',
|
'No tasks found.' => 'Задач не найдено.',
|
||||||
// 'Keyboard shortcut: "%s"' => '',
|
'Keyboard shortcut: "%s"' => 'Сочетание клавиш: "%s"',
|
||||||
// 'List' => '',
|
'List' => 'Список',
|
||||||
// 'Filter' => '',
|
'Filter' => 'Фильтр',
|
||||||
// 'Advanced search' => '',
|
'Advanced search' => 'Расширенный поиск',
|
||||||
// 'Example of query: ' => '',
|
'Example of query: ' => 'Пример запроса: ',
|
||||||
// 'Search by project: ' => '',
|
'Search by project: ' => 'Поиск по проекту: ',
|
||||||
// 'Search by column: ' => '',
|
'Search by column: ' => 'Поиск по колонкам: ',
|
||||||
// 'Search by assignee: ' => '',
|
'Search by assignee: ' => 'Поису по назначенному: ',
|
||||||
// 'Search by color: ' => '',
|
'Search by color: ' => 'Поиск по цвету: ',
|
||||||
// 'Search by category: ' => '',
|
'Search by category: ' => 'Поиск по категориям: ',
|
||||||
// 'Search by description: ' => '',
|
'Search by description: ' => 'Поиск по описанию: ',
|
||||||
// 'Search by due date: ' => '',
|
'Search by due date: ' => 'Поиск по дате завершения: ',
|
||||||
// 'Lead and Cycle time for "%s"' => '',
|
'Lead and Cycle time for "%s"' => 'Затраченное время и время цикла для "%s"',
|
||||||
// 'Average time spent into each column for "%s"' => '',
|
'Average time spent into each column for "%s"' => 'Затрачено времени в среднем в каждой колонке для "%s"',
|
||||||
// 'Average time spent into each column' => '',
|
'Average time spent into each column' => 'Затрачено времени в среднем в каждой колонке',
|
||||||
// 'Average time spent' => '',
|
'Average time spent' => 'Затрачено времени в среднем',
|
||||||
// 'This chart show the average time spent into each column for the last %d tasks.' => '',
|
'This chart show the average time spent into each column for the last %d tasks.' => 'Эта диаграмма показывает среднее время, проведенное задачами в каждой колонке за последний %d.',
|
||||||
// 'Average Lead and Cycle time' => '',
|
'Average Lead and Cycle time' => 'Среднее время выполнения и цикла',
|
||||||
// 'Average lead time: ' => '',
|
'Average lead time: ' => 'Среднее время выполнения',
|
||||||
// 'Average cycle time: ' => '',
|
'Average cycle time: ' => 'Среднее время цикла',
|
||||||
// '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.' => '',
|
'This chart show the average lead and cycle time for the last %d tasks over the time.' => 'Эта диаграма показывает среднее время выполнения и цикла задачь в последние %d.',
|
||||||
// 'Average time into each column' => '',
|
'Average time into each column' => 'Среднее время в каждом столбце',
|
||||||
// 'Lead and cycle time' => '',
|
'Lead and cycle time' => 'Время выполнения и цикла',
|
||||||
// 'Google Authentication' => '',
|
'Google Authentication' => 'Авторизация Google',
|
||||||
// 'Help on Google authentication' => '',
|
'Help on Google authentication' => 'Помощь в авторизации Google',
|
||||||
// 'Github Authentication' => '',
|
'Github Authentication' => 'Авторизация Github',
|
||||||
// 'Help on Github authentication' => '',
|
'Help on Github authentication' => 'Помощь в авторизации Github',
|
||||||
// 'Channel/Group/User (Optional)' => '',
|
'Channel/Group/User (Optional)' => 'Канал/Группа/Пользователь (опционально)',
|
||||||
// 'Lead time: ' => '',
|
'Lead time: ' => 'Время выполнения:',
|
||||||
// 'Cycle time: ' => '',
|
'Cycle time: ' => 'Время цикла:',
|
||||||
// 'Time spent into each column' => '',
|
'Time spent into each column' => 'Время, проведенное в каждой колонке',
|
||||||
// 'The lead time is the duration between the task creation and the completion.' => '',
|
'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.' => '',
|
'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.' => '',
|
// 'If the task is not closed the current time is used instead of the completion date.' => '',
|
||||||
// 'Set automatically the start date' => '',
|
'Set automatically the start date' => 'Установить автоматическую дату начала',
|
||||||
// 'Edit Authentication' => '',
|
'Edit Authentication' => 'Редактировать авторизацию',
|
||||||
// 'Google Id' => '',
|
'Google Id' => 'Google I',
|
||||||
// 'Github Id' => '',
|
'Github Id' => 'Github Id',
|
||||||
// 'Remote user' => '',
|
'Remote user' => 'Удаленный пользователь',
|
||||||
// 'Remote users do not store their password in Kanboard database, examples: LDAP, Google and Github accounts.' => '',
|
'Remote users do not store their password in Kanboard database, examples: LDAP, Google and Github accounts.' => 'Учетные данные для входа через LDAP, Google и Github не будут сохранены в Kanboard.',
|
||||||
// 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => '',
|
'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => 'Если вы установите флажок "Запретить форму входа", учетные данные, введенные в форму входа будет игнорироваться.',
|
||||||
// 'By @%s on Gitlab' => '',
|
'By @%s on Gitlab' => 'От @%s на Gitlab',
|
||||||
// 'Gitlab issue comment created' => '',
|
'Gitlab issue comment created' => 'Был создан комментарий к задаче на Gitlab',
|
||||||
// 'New remote user' => '',
|
'New remote user' => 'Новый удаленный пользователь',
|
||||||
// 'New local user' => '',
|
'New local user' => 'Новый локальный пользователь',
|
||||||
// 'Default task color' => '',
|
'Default task color' => 'Стандартные цвета задач',
|
||||||
// 'Hide sidebar' => '',
|
'Hide sidebar' => 'Свернуть сайдбар',
|
||||||
// 'Expand sidebar' => '',
|
'Expand sidebar' => 'Показать сайдбар',
|
||||||
// 'This feature does not work with all browsers.' => '',
|
'This feature does not work with all browsers.' => 'Эта функция доступна не во всех браузерах.',
|
||||||
// 'There is no destination project available.' => '',
|
'There is no destination project available.' => 'Нет доступного для назначения проекта.',
|
||||||
// 'Trigger automatically subtask time tracking' => '',
|
'Trigger automatically subtask time tracking' => 'Триггер автоматического отслеживания времени подзадач',
|
||||||
// 'Include closed tasks in the cumulative flow diagram' => '',
|
'Include closed tasks in the cumulative flow diagram' => 'Включить в диаграмму закрытые задачи',
|
||||||
// 'Current swimlane: %s' => '',
|
'Current swimlane: %s' => 'Текущая дорожка: %s',
|
||||||
// 'Current column: %s' => '',
|
'Current column: %s' => 'Текущая колонка: %s',
|
||||||
// 'Current category: %s' => '',
|
'Current category: %s' => 'Текущая категория: %s',
|
||||||
// 'no category' => '',
|
'no category' => 'без категории',
|
||||||
// 'Current assignee: %s' => '',
|
'Current assignee: %s' => 'Current assignee: %s',
|
||||||
// 'not assigned' => '',
|
'not assigned' => 'не назначен',
|
||||||
// 'Author:' => '',
|
'Author:' => 'Автор:',
|
||||||
// 'contributors' => '',
|
'contributors' => 'соавторы',
|
||||||
// 'License:' => '',
|
'License:' => 'Лицензия:',
|
||||||
// 'License' => '',
|
'License' => 'Лицензия',
|
||||||
// 'Project Administrator' => '',
|
'Project Administrator' => 'Администратор проекта',
|
||||||
// 'Enter the text below' => '',
|
'Enter the text below' => 'Введите текст ниже',
|
||||||
// 'Gantt chart for %s' => '',
|
'Gantt chart for %s' => 'Диаграмма Гантта для %s',
|
||||||
// 'Sort by position' => '',
|
'Sort by position' => 'Сортировать по позиции',
|
||||||
// 'Sort by date' => '',
|
'Sort by date' => 'Сортировать по дате',
|
||||||
// 'Add task' => '',
|
'Add task' => 'Добавить задачу',
|
||||||
// 'Start date:' => '',
|
'Start date:' => 'Дата начала:',
|
||||||
// 'Due date:' => '',
|
'Due date:' => 'Дата завершения:',
|
||||||
// 'There is no start date or due date for this task.' => '',
|
'There is no start date or due date for this task.' => 'Для этой задачи нет даты начала или завершения.',
|
||||||
// 'Moving or resizing a task will change the start and due date of the task.' => '',
|
'Moving or resizing a task will change the start and due date of the task.' => 'Изменение или перемещение задачи повлечет изменение даты начала завершения задачи.',
|
||||||
// 'There is no task in your project.' => '',
|
'There is no task in your project.' => 'В Вашем проекте задач нет.',
|
||||||
// 'Gantt chart' => '',
|
'Gantt chart' => 'Диаграмма Гантта',
|
||||||
// 'People who are project managers' => '',
|
'People who are project managers' => 'Люди, которые менеджеры проекта',
|
||||||
// 'People who are project members' => '',
|
'People who are project members' => 'Люди, которые участники проекта',
|
||||||
// 'NOK - Norwegian Krone' => '',
|
'NOK - Norwegian Krone' => 'НК - Норвежская крона',
|
||||||
// 'Show this column' => '',
|
'Show this column' => 'Показать эту колонку',
|
||||||
// 'Hide this column' => '',
|
'Hide this column' => 'Спрятать эту колонку',
|
||||||
// 'open file' => '',
|
'open file' => 'открыть файл',
|
||||||
// 'End date' => '',
|
'End date' => 'Дата завершения',
|
||||||
// 'Users overview' => '',
|
'Users overview' => 'Обзор пользователей',
|
||||||
// 'Managers' => '',
|
'Managers' => 'Менеджеры',
|
||||||
// 'Members' => '',
|
'Members' => 'Участники',
|
||||||
// 'Shared project' => '',
|
'Shared project' => 'Общие/публичные проекты',
|
||||||
// 'Project managers' => '',
|
'Project managers' => 'Менеджер проекта',
|
||||||
// 'Project members' => '',
|
'Project members' => 'Участники проекта',
|
||||||
// 'Gantt chart for all projects' => '',
|
'Gantt chart for all projects' => 'Диаграмма Гантта для всех проектов',
|
||||||
// 'Projects list' => '',
|
'Projects list' => 'Список проектов',
|
||||||
// 'Gantt chart for this project' => '',
|
'Gantt chart for this project' => 'Диаграмма Гантта для этого проекта',
|
||||||
// 'Project board' => '',
|
'Project board' => 'Доска проекта',
|
||||||
// 'End date:' => '',
|
'End date:' => 'Дата завершения:',
|
||||||
// 'There is no start date or end date for this project.' => '',
|
'There is no start date or end date for this project.' => 'В проекте не указаны дата начала или завершения.',
|
||||||
// 'Projects Gantt chart' => '',
|
'Projects Gantt chart' => 'Диаграмма Гантта проектов',
|
||||||
// 'Start date: %s' => '',
|
'Start date: %s' => 'Дата начала: %s',
|
||||||
// 'End date: %s' => '',
|
'End date: %s' => 'Дата завершения: %s',
|
||||||
// 'Link type' => '',
|
'Link type' => 'Тип ссылки',
|
||||||
// 'Change task color when using a specific task link' => '',
|
'Change task color when using a specific task link' => 'Изменение цвета задач при использовании ссылки на определенные задачи',
|
||||||
// 'Task link creation or modification' => '',
|
'Task link creation or modification' => 'Ссылка на создание или модификацию задачи',
|
||||||
// 'Login with my Gitlab Account' => '',
|
'Login with my Gitlab Account' => 'Авторизоваться через аккаунт Gitlab',
|
||||||
// 'Milestone' => '',
|
'Milestone' => 'Веха',
|
||||||
// 'Gitlab Authentication' => '',
|
'Gitlab Authentication' => 'Авторизация через Gitlab',
|
||||||
// 'Help on Gitlab authentication' => '',
|
'Help on Gitlab authentication' => 'Помощь а авторизации через Gitlab',
|
||||||
// 'Gitlab Id' => '',
|
'Gitlab Id' => 'Gitlab Id',
|
||||||
// 'Gitlab Account' => '',
|
'Gitlab Account' => 'Аккаунт Gitlab',
|
||||||
// 'Link my Gitlab Account' => '',
|
'Link my Gitlab Account' => 'Привязать аккаунт Gitlab',
|
||||||
// 'Unlink my Gitlab Account' => '',
|
'Unlink my Gitlab Account' => 'Отвязать аккаунт Gitlab',
|
||||||
// 'Documentation: %s' => '',
|
'Documentation: %s' => 'Документация: %s',
|
||||||
// 'Switch to the Gantt chart view' => '',
|
'Switch to the Gantt chart view' => 'Переключиться в режим диаграммы Гантта',
|
||||||
// 'Reset the search/filter box' => '',
|
'Reset the search/filter box' => 'Сбросить поиск/фильтр',
|
||||||
// 'Documentation' => '',
|
'Documentation' => 'Документация',
|
||||||
// 'Table of contents' => '',
|
'Table of contents' => 'Сожержание',
|
||||||
// 'Gantt' => '',
|
'Gantt' => 'Гантт',
|
||||||
// 'Help with project permissions' => '',
|
'Help with project permissions' => 'Помощь с правами доступа по проекту',
|
||||||
|
// 'Author' => '',
|
||||||
|
// 'Version' => '',
|
||||||
|
// 'Plugins' => '',
|
||||||
|
// 'There is no plugin loaded.' => '',
|
||||||
|
// 'Set maximum column height' => '',
|
||||||
|
// 'Remove maximum column height' => '',
|
||||||
|
// 'My notifications' => '',
|
||||||
|
// 'Custom filters' => '',
|
||||||
|
// 'Your custom filter have been created successfully.' => '',
|
||||||
|
// 'Unable to create your custom filter.' => '',
|
||||||
|
// 'Custom filter removed successfully.' => '',
|
||||||
|
// 'Unable to remove this custom filter.' => '',
|
||||||
|
// 'Edit custom filter' => '',
|
||||||
|
// 'Your custom filter have been updated successfully.' => '',
|
||||||
|
// 'Unable to update custom filter.' => '',
|
||||||
|
// 'Web' => '',
|
||||||
|
// 'New attachment on task #%d: %s' => '',
|
||||||
|
// 'New comment on task #%d' => '',
|
||||||
|
// 'Comment updated on task #%d' => '',
|
||||||
|
// 'New subtask on task #%d' => '',
|
||||||
|
// 'Subtask updated on task #%d' => '',
|
||||||
|
// 'New task #%d: %s' => '',
|
||||||
|
// 'Task updated #%d' => '',
|
||||||
|
// 'Task #%d closed' => '',
|
||||||
|
// 'Task #%d opened' => '',
|
||||||
|
// 'Column changed for task #%d' => '',
|
||||||
|
// 'New position for task #%d' => '',
|
||||||
|
// 'Swimlane changed for task #%d' => '',
|
||||||
|
// 'Assignee changed on task #%d' => '',
|
||||||
|
// '%d overdue tasks' => '',
|
||||||
|
// 'Task #%d is overdue' => '',
|
||||||
|
// 'No new notifications.' => '',
|
||||||
|
// 'Mark all as read' => '',
|
||||||
|
// 'Mark as read' => '',
|
||||||
|
// 'Total number of tasks in this column across all swimlanes' => '',
|
||||||
|
// 'Collapse swimlane' => '',
|
||||||
|
// 'Expand swimlane' => '',
|
||||||
|
// 'Add a new filter' => '',
|
||||||
|
// 'Share with all project members' => '',
|
||||||
|
// 'Shared' => '',
|
||||||
|
// 'Owner' => '',
|
||||||
|
// 'Unread notifications' => '',
|
||||||
|
// 'My filters' => '',
|
||||||
|
// 'Notification methods:' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -395,8 +395,6 @@ return array(
|
||||||
'Remote' => 'Udaljno',
|
'Remote' => 'Udaljno',
|
||||||
'Enabled' => 'Omogući',
|
'Enabled' => 'Omogući',
|
||||||
'Disabled' => 'Onemogući',
|
'Disabled' => 'Onemogući',
|
||||||
'Google account linked' => 'Połączone konto Google',
|
|
||||||
'Github account linked' => 'Połączone konto Github',
|
|
||||||
'Username:' => 'Korisničko ime:',
|
'Username:' => 'Korisničko ime:',
|
||||||
'Name:' => 'Ime i Prezime',
|
'Name:' => 'Ime i Prezime',
|
||||||
'Email:' => 'Email: ',
|
'Email:' => 'Email: ',
|
||||||
|
@ -667,75 +665,26 @@ return array(
|
||||||
// 'Horizontal scrolling' => '',
|
// 'Horizontal scrolling' => '',
|
||||||
// 'Compact/wide view' => '',
|
// 'Compact/wide view' => '',
|
||||||
// 'No results match:' => '',
|
// 'No results match:' => '',
|
||||||
// 'Remove hourly rate' => '',
|
|
||||||
// 'Do you really want to remove this hourly rate?' => '',
|
|
||||||
// 'Hourly rates' => '',
|
|
||||||
// 'Hourly rate' => '',
|
|
||||||
// 'Currency' => '',
|
// 'Currency' => '',
|
||||||
// 'Effective date' => '',
|
|
||||||
// 'Add new rate' => '',
|
|
||||||
// 'Rate removed successfully.' => '',
|
|
||||||
// 'Unable to remove this rate.' => '',
|
|
||||||
// 'Unable to save the hourly rate.' => '',
|
|
||||||
// 'Hourly rate created successfully.' => '',
|
|
||||||
// 'Start time' => '',
|
|
||||||
// 'End time' => '',
|
|
||||||
// 'Comment' => '',
|
|
||||||
// 'All day' => '',
|
|
||||||
// 'Day' => '',
|
|
||||||
// 'Manage timetable' => '',
|
|
||||||
// 'Overtime timetable' => '',
|
|
||||||
// 'Time off timetable' => '',
|
|
||||||
// 'Timetable' => '',
|
|
||||||
// 'Work timetable' => '',
|
|
||||||
// 'Week timetable' => '',
|
|
||||||
// 'Day timetable' => '',
|
|
||||||
// 'From' => '',
|
|
||||||
// 'To' => '',
|
|
||||||
// 'Time slot created successfully.' => '',
|
|
||||||
// 'Unable to save this time slot.' => '',
|
|
||||||
// 'Time slot removed successfully.' => '',
|
|
||||||
// 'Unable to remove this time slot.' => '',
|
|
||||||
// 'Do you really want to remove this time slot?' => '',
|
|
||||||
// 'Remove time slot' => '',
|
|
||||||
// 'Add new time slot' => '',
|
|
||||||
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
|
|
||||||
// 'Files' => '',
|
// 'Files' => '',
|
||||||
// 'Images' => '',
|
// 'Images' => '',
|
||||||
// 'Private project' => '',
|
// 'Private project' => '',
|
||||||
// 'Amount' => '',
|
|
||||||
// 'AUD - Australian Dollar' => '',
|
// 'AUD - Australian Dollar' => '',
|
||||||
// 'Budget' => '',
|
|
||||||
// 'Budget line' => '',
|
|
||||||
// 'Budget line removed successfully.' => '',
|
|
||||||
// 'Budget lines' => '',
|
|
||||||
// 'CAD - Canadian Dollar' => '',
|
// 'CAD - Canadian Dollar' => '',
|
||||||
// 'CHF - Swiss Francs' => '',
|
// 'CHF - Swiss Francs' => '',
|
||||||
// 'Cost' => '',
|
|
||||||
// 'Cost breakdown' => '',
|
|
||||||
// 'Custom Stylesheet' => '',
|
// 'Custom Stylesheet' => '',
|
||||||
// 'download' => '',
|
// 'download' => '',
|
||||||
// 'Do you really want to remove this budget line?' => '',
|
|
||||||
// 'EUR - Euro' => '',
|
// 'EUR - Euro' => '',
|
||||||
// 'Expenses' => '',
|
|
||||||
// 'GBP - British Pound' => '',
|
// 'GBP - British Pound' => '',
|
||||||
// 'INR - Indian Rupee' => '',
|
// 'INR - Indian Rupee' => '',
|
||||||
// 'JPY - Japanese Yen' => '',
|
// 'JPY - Japanese Yen' => '',
|
||||||
// 'New budget line' => '',
|
|
||||||
// 'NZD - New Zealand Dollar' => '',
|
// 'NZD - New Zealand Dollar' => '',
|
||||||
// 'Remove a budget line' => '',
|
|
||||||
// 'Remove budget line' => '',
|
|
||||||
// 'RSD - Serbian dinar' => '',
|
// 'RSD - Serbian dinar' => '',
|
||||||
// 'The budget line have been created successfully.' => '',
|
|
||||||
// 'Unable to create the budget line.' => '',
|
|
||||||
// 'Unable to remove this budget line.' => '',
|
|
||||||
// 'USD - US Dollar' => '',
|
// 'USD - US Dollar' => '',
|
||||||
// 'Remaining' => '',
|
|
||||||
// 'Destination column' => '',
|
// 'Destination column' => '',
|
||||||
// 'Move the task to another column when assigned to a user' => '',
|
// 'Move the task to another column when assigned to a user' => '',
|
||||||
// 'Move the task to another column when assignee is cleared' => '',
|
// 'Move the task to another column when assignee is cleared' => '',
|
||||||
// 'Source column' => '',
|
// 'Source column' => '',
|
||||||
// 'Show subtask estimates (forecast of future work)' => '',
|
|
||||||
// 'Transitions' => '',
|
// 'Transitions' => '',
|
||||||
// 'Executer' => '',
|
// 'Executer' => '',
|
||||||
// 'Time spent in the column' => '',
|
// 'Time spent in the column' => '',
|
||||||
|
@ -746,7 +695,6 @@ return array(
|
||||||
// 'Rate' => '',
|
// 'Rate' => '',
|
||||||
// 'Change reference currency' => '',
|
// 'Change reference currency' => '',
|
||||||
// 'Add a new currency rate' => '',
|
// 'Add a new currency rate' => '',
|
||||||
// 'Currency rates are used to calculate project budget.' => '',
|
|
||||||
// 'Reference currency' => '',
|
// 'Reference currency' => '',
|
||||||
// 'The currency rate have been added successfully.' => '',
|
// 'The currency rate have been added successfully.' => '',
|
||||||
// 'Unable to add this currency rate.' => '',
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
@ -878,9 +826,6 @@ return array(
|
||||||
// '%s moved the task #%d to the first swimlane' => '',
|
// '%s moved the task #%d to the first swimlane' => '',
|
||||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||||
// 'Swimlane' => '',
|
// 'Swimlane' => '',
|
||||||
// 'Budget overview' => '',
|
|
||||||
// 'Type' => '',
|
|
||||||
// 'There is not enough data to show something.' => '',
|
|
||||||
// 'Gravatar' => '',
|
// 'Gravatar' => '',
|
||||||
// 'Hipchat' => '',
|
// 'Hipchat' => '',
|
||||||
// 'Slack' => '',
|
// 'Slack' => '',
|
||||||
|
@ -1067,4 +1012,48 @@ return array(
|
||||||
// 'Table of contents' => '',
|
// 'Table of contents' => '',
|
||||||
// 'Gantt' => '',
|
// 'Gantt' => '',
|
||||||
// 'Help with project permissions' => '',
|
// 'Help with project permissions' => '',
|
||||||
|
// 'Author' => '',
|
||||||
|
// 'Version' => '',
|
||||||
|
// 'Plugins' => '',
|
||||||
|
// 'There is no plugin loaded.' => '',
|
||||||
|
// 'Set maximum column height' => '',
|
||||||
|
// 'Remove maximum column height' => '',
|
||||||
|
// 'My notifications' => '',
|
||||||
|
// 'Custom filters' => '',
|
||||||
|
// 'Your custom filter have been created successfully.' => '',
|
||||||
|
// 'Unable to create your custom filter.' => '',
|
||||||
|
// 'Custom filter removed successfully.' => '',
|
||||||
|
// 'Unable to remove this custom filter.' => '',
|
||||||
|
// 'Edit custom filter' => '',
|
||||||
|
// 'Your custom filter have been updated successfully.' => '',
|
||||||
|
// 'Unable to update custom filter.' => '',
|
||||||
|
// 'Web' => '',
|
||||||
|
// 'New attachment on task #%d: %s' => '',
|
||||||
|
// 'New comment on task #%d' => '',
|
||||||
|
// 'Comment updated on task #%d' => '',
|
||||||
|
// 'New subtask on task #%d' => '',
|
||||||
|
// 'Subtask updated on task #%d' => '',
|
||||||
|
// 'New task #%d: %s' => '',
|
||||||
|
// 'Task updated #%d' => '',
|
||||||
|
// 'Task #%d closed' => '',
|
||||||
|
// 'Task #%d opened' => '',
|
||||||
|
// 'Column changed for task #%d' => '',
|
||||||
|
// 'New position for task #%d' => '',
|
||||||
|
// 'Swimlane changed for task #%d' => '',
|
||||||
|
// 'Assignee changed on task #%d' => '',
|
||||||
|
// '%d overdue tasks' => '',
|
||||||
|
// 'Task #%d is overdue' => '',
|
||||||
|
// 'No new notifications.' => '',
|
||||||
|
// 'Mark all as read' => '',
|
||||||
|
// 'Mark as read' => '',
|
||||||
|
// 'Total number of tasks in this column across all swimlanes' => '',
|
||||||
|
// 'Collapse swimlane' => '',
|
||||||
|
// 'Expand swimlane' => '',
|
||||||
|
// 'Add a new filter' => '',
|
||||||
|
// 'Share with all project members' => '',
|
||||||
|
// 'Shared' => '',
|
||||||
|
// 'Owner' => '',
|
||||||
|
// 'Unread notifications' => '',
|
||||||
|
// 'My filters' => '',
|
||||||
|
// 'Notification methods:' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -395,8 +395,6 @@ return array(
|
||||||
'Remote' => 'Fjärr',
|
'Remote' => 'Fjärr',
|
||||||
'Enabled' => 'Aktiverad',
|
'Enabled' => 'Aktiverad',
|
||||||
'Disabled' => 'Inaktiverad',
|
'Disabled' => 'Inaktiverad',
|
||||||
'Google account linked' => 'Googlekonto länkat',
|
|
||||||
'Github account linked' => 'Githubkonto länkat',
|
|
||||||
'Username:' => 'Användarnam:',
|
'Username:' => 'Användarnam:',
|
||||||
'Name:' => 'Namn:',
|
'Name:' => 'Namn:',
|
||||||
'Email:' => 'E-post:',
|
'Email:' => 'E-post:',
|
||||||
|
@ -667,75 +665,26 @@ return array(
|
||||||
'Horizontal scrolling' => 'Horisontell scroll',
|
'Horizontal scrolling' => 'Horisontell scroll',
|
||||||
'Compact/wide view' => 'Kompakt/bred vy',
|
'Compact/wide view' => 'Kompakt/bred vy',
|
||||||
'No results match:' => 'Inga matchande resultat',
|
'No results match:' => 'Inga matchande resultat',
|
||||||
'Remove hourly rate' => 'Ta bort timtaxa',
|
|
||||||
'Do you really want to remove this hourly rate?' => 'Vill du verkligen ta bort denna timtaxa?',
|
|
||||||
'Hourly rates' => 'Timtaxor',
|
|
||||||
'Hourly rate' => 'Timtaxa',
|
|
||||||
'Currency' => 'Valuta',
|
'Currency' => 'Valuta',
|
||||||
'Effective date' => 'Giltighetsdatum',
|
|
||||||
'Add new rate' => 'Lägg till ny taxa',
|
|
||||||
'Rate removed successfully.' => 'Taxan togs bort.',
|
|
||||||
'Unable to remove this rate.' => 'Kunde inte ta bort taxan.',
|
|
||||||
'Unable to save the hourly rate.' => 'Kunde inte spara timtaxan.',
|
|
||||||
'Hourly rate created successfully.' => 'Timtaxan skapades.',
|
|
||||||
'Start time' => 'Starttid',
|
|
||||||
'End time' => 'Sluttid',
|
|
||||||
'Comment' => 'Kommentar',
|
|
||||||
'All day' => 'Hela dagen',
|
|
||||||
'Day' => 'Dag',
|
|
||||||
'Manage timetable' => 'Hantera timplan',
|
|
||||||
'Overtime timetable' => 'Övertidstimplan',
|
|
||||||
'Time off timetable' => 'Ledighetstimplan',
|
|
||||||
'Timetable' => 'Timplan',
|
|
||||||
'Work timetable' => 'Arbetstimplan',
|
|
||||||
'Week timetable' => 'Veckotidplan',
|
|
||||||
'Day timetable' => 'Dagstimplan',
|
|
||||||
'From' => 'Från',
|
|
||||||
'To' => 'Till',
|
|
||||||
'Time slot created successfully.' => 'Tidslucka skapad.',
|
|
||||||
'Unable to save this time slot.' => 'Kunde inte spara tidsluckan.',
|
|
||||||
'Time slot removed successfully.' => 'Tidsluckan tog bort.',
|
|
||||||
'Unable to remove this time slot.' => 'Kunde inte ta bort tidsluckan.',
|
|
||||||
'Do you really want to remove this time slot?' => 'Vill du verkligen ta bort tidsluckan?',
|
|
||||||
'Remove time slot' => 'Ta bort tidslucka',
|
|
||||||
'Add new time slot' => 'Lägg till ny tidslucka',
|
|
||||||
'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => 'Denna tidslucka används när kryssrutan "hela dagen" är kryssad vid schemalagd ledighet eller övertid.',
|
|
||||||
'Files' => 'Filer',
|
'Files' => 'Filer',
|
||||||
'Images' => 'Bilder',
|
'Images' => 'Bilder',
|
||||||
'Private project' => 'Privat projekt',
|
'Private project' => 'Privat projekt',
|
||||||
'Amount' => 'Belopp',
|
|
||||||
'AUD - Australian Dollar' => 'AUD - Australiska dollar',
|
'AUD - Australian Dollar' => 'AUD - Australiska dollar',
|
||||||
'Budget' => 'Budget',
|
|
||||||
'Budget line' => 'Budgetlinje',
|
|
||||||
'Budget line removed successfully.' => 'Budgetlinjen togs bort.',
|
|
||||||
'Budget lines' => 'Budgetlinjer',
|
|
||||||
'CAD - Canadian Dollar' => 'CAD - Kanadensiska dollar',
|
'CAD - Canadian Dollar' => 'CAD - Kanadensiska dollar',
|
||||||
'CHF - Swiss Francs' => 'CHF - Schweiziska Franc',
|
'CHF - Swiss Francs' => 'CHF - Schweiziska Franc',
|
||||||
'Cost' => 'Kostnad',
|
|
||||||
'Cost breakdown' => 'Kostnadssammanställning',
|
|
||||||
'Custom Stylesheet' => 'Anpassad stilmall',
|
'Custom Stylesheet' => 'Anpassad stilmall',
|
||||||
'download' => 'ladda ned',
|
'download' => 'ladda ned',
|
||||||
'Do you really want to remove this budget line?' => 'Vill du verkligen ta bort budgetlinjen?',
|
|
||||||
'EUR - Euro' => 'EUR - Euro',
|
'EUR - Euro' => 'EUR - Euro',
|
||||||
'Expenses' => 'Utgifter',
|
|
||||||
'GBP - British Pound' => 'GBP - Brittiska Pund',
|
'GBP - British Pound' => 'GBP - Brittiska Pund',
|
||||||
'INR - Indian Rupee' => 'INR - Indiska Rupier',
|
'INR - Indian Rupee' => 'INR - Indiska Rupier',
|
||||||
'JPY - Japanese Yen' => 'JPY - Japanska Yen',
|
'JPY - Japanese Yen' => 'JPY - Japanska Yen',
|
||||||
'New budget line' => 'Ny budgetlinje',
|
|
||||||
'NZD - New Zealand Dollar' => 'NZD - Nya Zeeländska Dollar',
|
'NZD - New Zealand Dollar' => 'NZD - Nya Zeeländska Dollar',
|
||||||
'Remove a budget line' => 'Ta bort en budgetlinje',
|
|
||||||
'Remove budget line' => 'Ta bort budgetlinje',
|
|
||||||
'RSD - Serbian dinar' => 'RSD - Serbiska Dinarer',
|
'RSD - Serbian dinar' => 'RSD - Serbiska Dinarer',
|
||||||
'The budget line have been created successfully.' => 'Budgetlinjen har skapats.',
|
|
||||||
'Unable to create the budget line.' => 'Kunde inte skapa budgetlinjen.',
|
|
||||||
'Unable to remove this budget line.' => 'Kunde inte ta bort budgetlinjen.',
|
|
||||||
'USD - US Dollar' => 'USD - Amerikanska Dollar',
|
'USD - US Dollar' => 'USD - Amerikanska Dollar',
|
||||||
'Remaining' => 'Återstående',
|
|
||||||
'Destination column' => 'Målkolumn',
|
'Destination column' => 'Målkolumn',
|
||||||
'Move the task to another column when assigned to a user' => 'Flytta uppgiften till en annan kolumn när den tilldelats en användare',
|
'Move the task to another column when assigned to a user' => 'Flytta uppgiften till en annan kolumn när den tilldelats en användare',
|
||||||
'Move the task to another column when assignee is cleared' => 'Flytta uppgiften till en annan kolumn när tilldelningen tas bort.',
|
'Move the task to another column when assignee is cleared' => 'Flytta uppgiften till en annan kolumn när tilldelningen tas bort.',
|
||||||
'Source column' => 'Källkolumn',
|
'Source column' => 'Källkolumn',
|
||||||
'Show subtask estimates (forecast of future work)' => 'Visa uppskattningar för deluppgifter (prognos för framtida arbete)',
|
|
||||||
'Transitions' => 'Övergångar',
|
'Transitions' => 'Övergångar',
|
||||||
'Executer' => 'Verkställare',
|
'Executer' => 'Verkställare',
|
||||||
'Time spent in the column' => 'Tid i kolumnen.',
|
'Time spent in the column' => 'Tid i kolumnen.',
|
||||||
|
@ -746,7 +695,6 @@ return array(
|
||||||
'Rate' => 'Kurs',
|
'Rate' => 'Kurs',
|
||||||
'Change reference currency' => 'Ändra referenskurs',
|
'Change reference currency' => 'Ändra referenskurs',
|
||||||
'Add a new currency rate' => 'Lägg till ny valutakurs',
|
'Add a new currency rate' => 'Lägg till ny valutakurs',
|
||||||
'Currency rates are used to calculate project budget.' => 'Valutakurser används för att beräkna projektbudget.',
|
|
||||||
'Reference currency' => 'Referensvaluta',
|
'Reference currency' => 'Referensvaluta',
|
||||||
'The currency rate have been added successfully.' => 'Valutakursen har lagts till.',
|
'The currency rate have been added successfully.' => 'Valutakursen har lagts till.',
|
||||||
'Unable to add this currency rate.' => 'Kunde inte lägga till valutakursen.',
|
'Unable to add this currency rate.' => 'Kunde inte lägga till valutakursen.',
|
||||||
|
@ -878,9 +826,6 @@ return array(
|
||||||
'%s moved the task #%d to the first swimlane' => '%s flyttade uppgiften #%d till första swimlane',
|
'%s moved the task #%d to the first swimlane' => '%s flyttade uppgiften #%d till första swimlane',
|
||||||
'%s moved the task #%d to the swimlane "%s"' => '%s flyttade uppgiften #%d till swimlane "%s"',
|
'%s moved the task #%d to the swimlane "%s"' => '%s flyttade uppgiften #%d till swimlane "%s"',
|
||||||
'Swimlane' => 'Swimlane',
|
'Swimlane' => 'Swimlane',
|
||||||
'Budget overview' => 'Budgetöversikt',
|
|
||||||
'Type' => 'Typ',
|
|
||||||
'There is not enough data to show something.' => 'Det finns inte tillräckligt mycket data för att visa något.',
|
|
||||||
'Gravatar' => 'Gravatar',
|
'Gravatar' => 'Gravatar',
|
||||||
'Hipchat' => 'Hipchat',
|
'Hipchat' => 'Hipchat',
|
||||||
'Slack' => 'Slack',
|
'Slack' => 'Slack',
|
||||||
|
@ -1067,4 +1012,48 @@ return array(
|
||||||
// 'Table of contents' => '',
|
// 'Table of contents' => '',
|
||||||
// 'Gantt' => '',
|
// 'Gantt' => '',
|
||||||
// 'Help with project permissions' => '',
|
// 'Help with project permissions' => '',
|
||||||
|
// 'Author' => '',
|
||||||
|
// 'Version' => '',
|
||||||
|
// 'Plugins' => '',
|
||||||
|
// 'There is no plugin loaded.' => '',
|
||||||
|
// 'Set maximum column height' => '',
|
||||||
|
// 'Remove maximum column height' => '',
|
||||||
|
// 'My notifications' => '',
|
||||||
|
// 'Custom filters' => '',
|
||||||
|
// 'Your custom filter have been created successfully.' => '',
|
||||||
|
// 'Unable to create your custom filter.' => '',
|
||||||
|
// 'Custom filter removed successfully.' => '',
|
||||||
|
// 'Unable to remove this custom filter.' => '',
|
||||||
|
// 'Edit custom filter' => '',
|
||||||
|
// 'Your custom filter have been updated successfully.' => '',
|
||||||
|
// 'Unable to update custom filter.' => '',
|
||||||
|
// 'Web' => '',
|
||||||
|
// 'New attachment on task #%d: %s' => '',
|
||||||
|
// 'New comment on task #%d' => '',
|
||||||
|
// 'Comment updated on task #%d' => '',
|
||||||
|
// 'New subtask on task #%d' => '',
|
||||||
|
// 'Subtask updated on task #%d' => '',
|
||||||
|
// 'New task #%d: %s' => '',
|
||||||
|
// 'Task updated #%d' => '',
|
||||||
|
// 'Task #%d closed' => '',
|
||||||
|
// 'Task #%d opened' => '',
|
||||||
|
// 'Column changed for task #%d' => '',
|
||||||
|
// 'New position for task #%d' => '',
|
||||||
|
// 'Swimlane changed for task #%d' => '',
|
||||||
|
// 'Assignee changed on task #%d' => '',
|
||||||
|
// '%d overdue tasks' => '',
|
||||||
|
// 'Task #%d is overdue' => '',
|
||||||
|
// 'No new notifications.' => '',
|
||||||
|
// 'Mark all as read' => '',
|
||||||
|
// 'Mark as read' => '',
|
||||||
|
// 'Total number of tasks in this column across all swimlanes' => '',
|
||||||
|
// 'Collapse swimlane' => '',
|
||||||
|
// 'Expand swimlane' => '',
|
||||||
|
// 'Add a new filter' => '',
|
||||||
|
// 'Share with all project members' => '',
|
||||||
|
// 'Shared' => '',
|
||||||
|
// 'Owner' => '',
|
||||||
|
// 'Unread notifications' => '',
|
||||||
|
// 'My filters' => '',
|
||||||
|
// 'Notification methods:' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -395,8 +395,6 @@ return array(
|
||||||
'Remote' => 'รีโมท',
|
'Remote' => 'รีโมท',
|
||||||
'Enabled' => 'เปิดการใช้',
|
'Enabled' => 'เปิดการใช้',
|
||||||
'Disabled' => 'ปิดการใช้',
|
'Disabled' => 'ปิดการใช้',
|
||||||
'Google account linked' => 'เชื่อมกับกูเกิลแอคเคาท์',
|
|
||||||
'Github account linked' => 'เชื่อมกับกิทฮับแอคเคาท์',
|
|
||||||
'Username:' => 'ชื่อผู้ใช้:',
|
'Username:' => 'ชื่อผู้ใช้:',
|
||||||
'Name:' => 'ชื่อ:',
|
'Name:' => 'ชื่อ:',
|
||||||
'Email:' => 'อีเมล:',
|
'Email:' => 'อีเมล:',
|
||||||
|
@ -667,75 +665,26 @@ return array(
|
||||||
'Horizontal scrolling' => 'เลื่อนตามแนวนอน',
|
'Horizontal scrolling' => 'เลื่อนตามแนวนอน',
|
||||||
'Compact/wide view' => 'พอดี/กว้าง มุมมอง',
|
'Compact/wide view' => 'พอดี/กว้าง มุมมอง',
|
||||||
'No results match:' => 'ไม่มีผลลัพท์ที่ตรง',
|
'No results match:' => 'ไม่มีผลลัพท์ที่ตรง',
|
||||||
'Remove hourly rate' => 'ลบอัตรารายชั่วโมง',
|
|
||||||
'Do you really want to remove this hourly rate?' => 'คุณต้องการลบอัตรารายชั่วโมง?',
|
|
||||||
'Hourly rates' => 'อัตรารายชั่วโมง',
|
|
||||||
'Hourly rate' => 'อัตรารายชั่วโมง',
|
|
||||||
'Currency' => 'สกุลเงิน',
|
'Currency' => 'สกุลเงิน',
|
||||||
'Effective date' => 'วันที่จ่าย',
|
|
||||||
'Add new rate' => 'เพิ่มอัตราใหม่',
|
|
||||||
'Rate removed successfully.' => 'ลบอัตราเรียบร้อยแล้ว',
|
|
||||||
'Unable to remove this rate.' => 'ไม่สามารถลบอัตรานี้ได้',
|
|
||||||
'Unable to save the hourly rate.' => 'ไม่สามารถบันทึกอัตรารายชั่วโมง',
|
|
||||||
'Hourly rate created successfully.' => 'อัตรารายชั่วโมงสร้างเรียบร้อยแล้ว',
|
|
||||||
'Start time' => 'เวลาเริ่มต้น',
|
|
||||||
'End time' => 'เวลาจบ',
|
|
||||||
'Comment' => 'ความคิดเห็น',
|
|
||||||
'All day' => 'ทั้งวัน',
|
|
||||||
'Day' => 'วัน',
|
|
||||||
'Manage timetable' => 'จัดการตารางเวลา',
|
|
||||||
'Overtime timetable' => 'ตารางเวลาโอที',
|
|
||||||
'Time off timetable' => 'ตารางเวลาวันหยุด',
|
|
||||||
'Timetable' => 'ตารางเวลา',
|
|
||||||
'Work timetable' => 'ตารางเวลางาน',
|
|
||||||
'Week timetable' => 'ตารางเวลาสัปดาห์',
|
|
||||||
'Day timetable' => 'ตารางเวลาวัน',
|
|
||||||
'From' => 'จาก',
|
|
||||||
'To' => 'ถึง',
|
|
||||||
'Time slot created successfully.' => 'สร้างช่วงเวลาเรียบร้อยแล้ว',
|
|
||||||
'Unable to save this time slot.' => 'ไม่สามารถบันทึกช่วงเวลานี้',
|
|
||||||
'Time slot removed successfully.' => 'ลบช่วงเวลาเรียบร้อยแล้ว',
|
|
||||||
'Unable to remove this time slot.' => 'ไม่สามารถลบช่วงเวลาได้',
|
|
||||||
'Do you really want to remove this time slot?' => 'คุณต้องการลบช่วงเวลานี้?',
|
|
||||||
'Remove time slot' => 'ลบช่วงเวลา',
|
|
||||||
'Add new time slot' => 'เพิ่มช่วงเวลาใหม่',
|
|
||||||
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
|
|
||||||
'Files' => 'ไฟล์',
|
'Files' => 'ไฟล์',
|
||||||
'Images' => 'รูปภาพ',
|
'Images' => 'รูปภาพ',
|
||||||
'Private project' => 'โปรเจคส่วนตัว',
|
'Private project' => 'โปรเจคส่วนตัว',
|
||||||
'Amount' => 'จำนวนเงิน',
|
|
||||||
// 'AUD - Australian Dollar' => '',
|
// 'AUD - Australian Dollar' => '',
|
||||||
'Budget' => 'งบประมาณ',
|
|
||||||
'Budget line' => 'วงเงินงบประมาณ',
|
|
||||||
'Budget line removed successfully.' => 'ลบวงเงินประมาณเรียบร้อยแล้ว',
|
|
||||||
'Budget lines' => 'วงเงินงบประมาณ',
|
|
||||||
// 'CAD - Canadian Dollar' => '',
|
// 'CAD - Canadian Dollar' => '',
|
||||||
// 'CHF - Swiss Francs' => '',
|
// 'CHF - Swiss Francs' => '',
|
||||||
'Cost' => 'มูลค่า',
|
|
||||||
'Cost breakdown' => 'รายละเอียดค่าใช้จ่าย',
|
|
||||||
// 'Custom Stylesheet' => '',
|
// 'Custom Stylesheet' => '',
|
||||||
'download' => 'ดาวน์โหลด',
|
'download' => 'ดาวน์โหลด',
|
||||||
'Do you really want to remove this budget line?' => 'คุณต้องการลบวงเงินงบประมาณนี้?',
|
|
||||||
// 'EUR - Euro' => '',
|
// 'EUR - Euro' => '',
|
||||||
'Expenses' => 'รายจ่าย',
|
|
||||||
// 'GBP - British Pound' => '',
|
// 'GBP - British Pound' => '',
|
||||||
// 'INR - Indian Rupee' => '',
|
// 'INR - Indian Rupee' => '',
|
||||||
// 'JPY - Japanese Yen' => '',
|
// 'JPY - Japanese Yen' => '',
|
||||||
'New budget line' => 'วงเงินงบประมาณใหม่',
|
|
||||||
// 'NZD - New Zealand Dollar' => '',
|
// 'NZD - New Zealand Dollar' => '',
|
||||||
'Remove a budget line' => 'ลบวงเงินประมาณ',
|
|
||||||
'Remove budget line' => 'ลบวงเงินประมาณ',
|
|
||||||
// 'RSD - Serbian dinar' => '',
|
// 'RSD - Serbian dinar' => '',
|
||||||
'The budget line have been created successfully.' => 'สร้างวงเงินงบประมาณเรียบร้อยแล้ว',
|
|
||||||
'Unable to create the budget line.' => 'ไม่สามารถสร้างวงเงินงบประมาณได้',
|
|
||||||
'Unable to remove this budget line.' => 'ไม่สามารถลบวงเงินงบประมาณนี้',
|
|
||||||
// 'USD - US Dollar' => '',
|
// 'USD - US Dollar' => '',
|
||||||
'Remaining' => 'เหลืออยู่',
|
|
||||||
'Destination column' => 'คอลัมน์เป้าหมาย',
|
'Destination column' => 'คอลัมน์เป้าหมาย',
|
||||||
'Move the task to another column when assigned to a user' => 'ย้ายงานไปคอลัมน์อื่นเมื่อกำหนดบุคคลรับผิดชอบ',
|
'Move the task to another column when assigned to a user' => 'ย้ายงานไปคอลัมน์อื่นเมื่อกำหนดบุคคลรับผิดชอบ',
|
||||||
'Move the task to another column when assignee is cleared' => 'ย้ายงานไปคอลัมน์อื่นเมื่อไม่กำหนดบุคคลรับผิดชอบ',
|
'Move the task to another column when assignee is cleared' => 'ย้ายงานไปคอลัมน์อื่นเมื่อไม่กำหนดบุคคลรับผิดชอบ',
|
||||||
'Source column' => 'คอลัมน์ต้นทาง',
|
'Source column' => 'คอลัมน์ต้นทาง',
|
||||||
// 'Show subtask estimates (forecast of future work)' => '',
|
|
||||||
'Transitions' => 'การเปลี่ยนคอลัมน์',
|
'Transitions' => 'การเปลี่ยนคอลัมน์',
|
||||||
'Executer' => 'ผู้ประมวลผล',
|
'Executer' => 'ผู้ประมวลผล',
|
||||||
'Time spent in the column' => 'เวลาที่ใช้ในคอลัมน์',
|
'Time spent in the column' => 'เวลาที่ใช้ในคอลัมน์',
|
||||||
|
@ -746,7 +695,6 @@ return array(
|
||||||
'Rate' => 'อัตรา',
|
'Rate' => 'อัตรา',
|
||||||
// 'Change reference currency' => '',
|
// 'Change reference currency' => '',
|
||||||
'Add a new currency rate' => 'เพิ่มอัตราแลกเปลี่ยนเงินตราใหม่',
|
'Add a new currency rate' => 'เพิ่มอัตราแลกเปลี่ยนเงินตราใหม่',
|
||||||
'Currency rates are used to calculate project budget.' => 'อัตราแลกเปลี่ยนเงินตราถูกใช้ในการคำนวณงบประมาณของโปรเจค',
|
|
||||||
// 'Reference currency' => '',
|
// 'Reference currency' => '',
|
||||||
// 'The currency rate have been added successfully.' => '',
|
// 'The currency rate have been added successfully.' => '',
|
||||||
// 'Unable to add this currency rate.' => '',
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
@ -878,9 +826,6 @@ return array(
|
||||||
// '%s moved the task #%d to the first swimlane' => '',
|
// '%s moved the task #%d to the first swimlane' => '',
|
||||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||||
// 'Swimlane' => '',
|
// 'Swimlane' => '',
|
||||||
// 'Budget overview' => '',
|
|
||||||
// 'Type' => '',
|
|
||||||
// 'There is not enough data to show something.' => '',
|
|
||||||
// 'Gravatar' => '',
|
// 'Gravatar' => '',
|
||||||
// 'Hipchat' => '',
|
// 'Hipchat' => '',
|
||||||
// 'Slack' => '',
|
// 'Slack' => '',
|
||||||
|
@ -1067,4 +1012,48 @@ return array(
|
||||||
// 'Table of contents' => '',
|
// 'Table of contents' => '',
|
||||||
// 'Gantt' => '',
|
// 'Gantt' => '',
|
||||||
// 'Help with project permissions' => '',
|
// 'Help with project permissions' => '',
|
||||||
|
// 'Author' => '',
|
||||||
|
// 'Version' => '',
|
||||||
|
// 'Plugins' => '',
|
||||||
|
// 'There is no plugin loaded.' => '',
|
||||||
|
// 'Set maximum column height' => '',
|
||||||
|
// 'Remove maximum column height' => '',
|
||||||
|
// 'My notifications' => '',
|
||||||
|
// 'Custom filters' => '',
|
||||||
|
// 'Your custom filter have been created successfully.' => '',
|
||||||
|
// 'Unable to create your custom filter.' => '',
|
||||||
|
// 'Custom filter removed successfully.' => '',
|
||||||
|
// 'Unable to remove this custom filter.' => '',
|
||||||
|
// 'Edit custom filter' => '',
|
||||||
|
// 'Your custom filter have been updated successfully.' => '',
|
||||||
|
// 'Unable to update custom filter.' => '',
|
||||||
|
// 'Web' => '',
|
||||||
|
// 'New attachment on task #%d: %s' => '',
|
||||||
|
// 'New comment on task #%d' => '',
|
||||||
|
// 'Comment updated on task #%d' => '',
|
||||||
|
// 'New subtask on task #%d' => '',
|
||||||
|
// 'Subtask updated on task #%d' => '',
|
||||||
|
// 'New task #%d: %s' => '',
|
||||||
|
// 'Task updated #%d' => '',
|
||||||
|
// 'Task #%d closed' => '',
|
||||||
|
// 'Task #%d opened' => '',
|
||||||
|
// 'Column changed for task #%d' => '',
|
||||||
|
// 'New position for task #%d' => '',
|
||||||
|
// 'Swimlane changed for task #%d' => '',
|
||||||
|
// 'Assignee changed on task #%d' => '',
|
||||||
|
// '%d overdue tasks' => '',
|
||||||
|
// 'Task #%d is overdue' => '',
|
||||||
|
// 'No new notifications.' => '',
|
||||||
|
// 'Mark all as read' => '',
|
||||||
|
// 'Mark as read' => '',
|
||||||
|
// 'Total number of tasks in this column across all swimlanes' => '',
|
||||||
|
// 'Collapse swimlane' => '',
|
||||||
|
// 'Expand swimlane' => '',
|
||||||
|
// 'Add a new filter' => '',
|
||||||
|
// 'Share with all project members' => '',
|
||||||
|
// 'Shared' => '',
|
||||||
|
// 'Owner' => '',
|
||||||
|
// 'Unread notifications' => '',
|
||||||
|
// 'My filters' => '',
|
||||||
|
// 'Notification methods:' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -395,8 +395,6 @@ return array(
|
||||||
'Remote' => 'Uzak',
|
'Remote' => 'Uzak',
|
||||||
'Enabled' => 'Etkinleştirildi',
|
'Enabled' => 'Etkinleştirildi',
|
||||||
'Disabled' => 'Devre dışı bırakıldı',
|
'Disabled' => 'Devre dışı bırakıldı',
|
||||||
'Google account linked' => 'Google hesabıyla bağlı',
|
|
||||||
'Github account linked' => 'Github hesabıyla bağlı',
|
|
||||||
'Username:' => 'Kullanıcı adı',
|
'Username:' => 'Kullanıcı adı',
|
||||||
'Name:' => 'Ad',
|
'Name:' => 'Ad',
|
||||||
'Email:' => 'E-Posta',
|
'Email:' => 'E-Posta',
|
||||||
|
@ -667,75 +665,26 @@ return array(
|
||||||
'Horizontal scrolling' => 'Geniş görünüm',
|
'Horizontal scrolling' => 'Geniş görünüm',
|
||||||
'Compact/wide view' => 'Ekrana sığdır / Geniş görünüm',
|
'Compact/wide view' => 'Ekrana sığdır / Geniş görünüm',
|
||||||
// 'No results match:' => '',
|
// 'No results match:' => '',
|
||||||
// 'Remove hourly rate' => '',
|
|
||||||
// 'Do you really want to remove this hourly rate?' => '',
|
|
||||||
// 'Hourly rates' => '',
|
|
||||||
// 'Hourly rate' => '',
|
|
||||||
// 'Currency' => '',
|
// 'Currency' => '',
|
||||||
// 'Effective date' => '',
|
|
||||||
// 'Add new rate' => '',
|
|
||||||
// 'Rate removed successfully.' => '',
|
|
||||||
// 'Unable to remove this rate.' => '',
|
|
||||||
// 'Unable to save the hourly rate.' => '',
|
|
||||||
// 'Hourly rate created successfully.' => '',
|
|
||||||
// 'Start time' => '',
|
|
||||||
// 'End time' => '',
|
|
||||||
// 'Comment' => '',
|
|
||||||
// 'All day' => '',
|
|
||||||
// 'Day' => '',
|
|
||||||
// 'Manage timetable' => '',
|
|
||||||
// 'Overtime timetable' => '',
|
|
||||||
// 'Time off timetable' => '',
|
|
||||||
// 'Timetable' => '',
|
|
||||||
// 'Work timetable' => '',
|
|
||||||
// 'Week timetable' => '',
|
|
||||||
// 'Day timetable' => '',
|
|
||||||
// 'From' => '',
|
|
||||||
// 'To' => '',
|
|
||||||
// 'Time slot created successfully.' => '',
|
|
||||||
// 'Unable to save this time slot.' => '',
|
|
||||||
// 'Time slot removed successfully.' => '',
|
|
||||||
// 'Unable to remove this time slot.' => '',
|
|
||||||
// 'Do you really want to remove this time slot?' => '',
|
|
||||||
// 'Remove time slot' => '',
|
|
||||||
// 'Add new time slot' => '',
|
|
||||||
// 'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '',
|
|
||||||
// 'Files' => '',
|
// 'Files' => '',
|
||||||
// 'Images' => '',
|
// 'Images' => '',
|
||||||
// 'Private project' => '',
|
// 'Private project' => '',
|
||||||
// 'Amount' => '',
|
|
||||||
// 'AUD - Australian Dollar' => '',
|
// 'AUD - Australian Dollar' => '',
|
||||||
// 'Budget' => '',
|
|
||||||
// 'Budget line' => '',
|
|
||||||
// 'Budget line removed successfully.' => '',
|
|
||||||
// 'Budget lines' => '',
|
|
||||||
// 'CAD - Canadian Dollar' => '',
|
// 'CAD - Canadian Dollar' => '',
|
||||||
// 'CHF - Swiss Francs' => '',
|
// 'CHF - Swiss Francs' => '',
|
||||||
// 'Cost' => '',
|
|
||||||
// 'Cost breakdown' => '',
|
|
||||||
// 'Custom Stylesheet' => '',
|
// 'Custom Stylesheet' => '',
|
||||||
// 'download' => '',
|
// 'download' => '',
|
||||||
// 'Do you really want to remove this budget line?' => '',
|
|
||||||
// 'EUR - Euro' => '',
|
// 'EUR - Euro' => '',
|
||||||
// 'Expenses' => '',
|
|
||||||
// 'GBP - British Pound' => '',
|
// 'GBP - British Pound' => '',
|
||||||
// 'INR - Indian Rupee' => '',
|
// 'INR - Indian Rupee' => '',
|
||||||
// 'JPY - Japanese Yen' => '',
|
// 'JPY - Japanese Yen' => '',
|
||||||
// 'New budget line' => '',
|
|
||||||
// 'NZD - New Zealand Dollar' => '',
|
// 'NZD - New Zealand Dollar' => '',
|
||||||
// 'Remove a budget line' => '',
|
|
||||||
// 'Remove budget line' => '',
|
|
||||||
// 'RSD - Serbian dinar' => '',
|
// 'RSD - Serbian dinar' => '',
|
||||||
// 'The budget line have been created successfully.' => '',
|
|
||||||
// 'Unable to create the budget line.' => '',
|
|
||||||
// 'Unable to remove this budget line.' => '',
|
|
||||||
// 'USD - US Dollar' => '',
|
// 'USD - US Dollar' => '',
|
||||||
// 'Remaining' => '',
|
|
||||||
// 'Destination column' => '',
|
// 'Destination column' => '',
|
||||||
// 'Move the task to another column when assigned to a user' => '',
|
// 'Move the task to another column when assigned to a user' => '',
|
||||||
// 'Move the task to another column when assignee is cleared' => '',
|
// 'Move the task to another column when assignee is cleared' => '',
|
||||||
// 'Source column' => '',
|
// 'Source column' => '',
|
||||||
// 'Show subtask estimates (forecast of future work)' => '',
|
|
||||||
// 'Transitions' => '',
|
// 'Transitions' => '',
|
||||||
// 'Executer' => '',
|
// 'Executer' => '',
|
||||||
// 'Time spent in the column' => '',
|
// 'Time spent in the column' => '',
|
||||||
|
@ -746,7 +695,6 @@ return array(
|
||||||
// 'Rate' => '',
|
// 'Rate' => '',
|
||||||
// 'Change reference currency' => '',
|
// 'Change reference currency' => '',
|
||||||
// 'Add a new currency rate' => '',
|
// 'Add a new currency rate' => '',
|
||||||
// 'Currency rates are used to calculate project budget.' => '',
|
|
||||||
// 'Reference currency' => '',
|
// 'Reference currency' => '',
|
||||||
// 'The currency rate have been added successfully.' => '',
|
// 'The currency rate have been added successfully.' => '',
|
||||||
// 'Unable to add this currency rate.' => '',
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
@ -878,9 +826,6 @@ return array(
|
||||||
// '%s moved the task #%d to the first swimlane' => '',
|
// '%s moved the task #%d to the first swimlane' => '',
|
||||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||||
// 'Swimlane' => '',
|
// 'Swimlane' => '',
|
||||||
// 'Budget overview' => '',
|
|
||||||
// 'Type' => '',
|
|
||||||
// 'There is not enough data to show something.' => '',
|
|
||||||
// 'Gravatar' => '',
|
// 'Gravatar' => '',
|
||||||
// 'Hipchat' => '',
|
// 'Hipchat' => '',
|
||||||
// 'Slack' => '',
|
// 'Slack' => '',
|
||||||
|
@ -1067,4 +1012,48 @@ return array(
|
||||||
// 'Table of contents' => '',
|
// 'Table of contents' => '',
|
||||||
// 'Gantt' => '',
|
// 'Gantt' => '',
|
||||||
// 'Help with project permissions' => '',
|
// 'Help with project permissions' => '',
|
||||||
|
// 'Author' => '',
|
||||||
|
// 'Version' => '',
|
||||||
|
// 'Plugins' => '',
|
||||||
|
// 'There is no plugin loaded.' => '',
|
||||||
|
// 'Set maximum column height' => '',
|
||||||
|
// 'Remove maximum column height' => '',
|
||||||
|
// 'My notifications' => '',
|
||||||
|
// 'Custom filters' => '',
|
||||||
|
// 'Your custom filter have been created successfully.' => '',
|
||||||
|
// 'Unable to create your custom filter.' => '',
|
||||||
|
// 'Custom filter removed successfully.' => '',
|
||||||
|
// 'Unable to remove this custom filter.' => '',
|
||||||
|
// 'Edit custom filter' => '',
|
||||||
|
// 'Your custom filter have been updated successfully.' => '',
|
||||||
|
// 'Unable to update custom filter.' => '',
|
||||||
|
// 'Web' => '',
|
||||||
|
// 'New attachment on task #%d: %s' => '',
|
||||||
|
// 'New comment on task #%d' => '',
|
||||||
|
// 'Comment updated on task #%d' => '',
|
||||||
|
// 'New subtask on task #%d' => '',
|
||||||
|
// 'Subtask updated on task #%d' => '',
|
||||||
|
// 'New task #%d: %s' => '',
|
||||||
|
// 'Task updated #%d' => '',
|
||||||
|
// 'Task #%d closed' => '',
|
||||||
|
// 'Task #%d opened' => '',
|
||||||
|
// 'Column changed for task #%d' => '',
|
||||||
|
// 'New position for task #%d' => '',
|
||||||
|
// 'Swimlane changed for task #%d' => '',
|
||||||
|
// 'Assignee changed on task #%d' => '',
|
||||||
|
// '%d overdue tasks' => '',
|
||||||
|
// 'Task #%d is overdue' => '',
|
||||||
|
// 'No new notifications.' => '',
|
||||||
|
// 'Mark all as read' => '',
|
||||||
|
// 'Mark as read' => '',
|
||||||
|
// 'Total number of tasks in this column across all swimlanes' => '',
|
||||||
|
// 'Collapse swimlane' => '',
|
||||||
|
// 'Expand swimlane' => '',
|
||||||
|
// 'Add a new filter' => '',
|
||||||
|
// 'Share with all project members' => '',
|
||||||
|
// 'Shared' => '',
|
||||||
|
// 'Owner' => '',
|
||||||
|
// 'Unread notifications' => '',
|
||||||
|
// 'My filters' => '',
|
||||||
|
// 'Notification methods:' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -395,8 +395,6 @@ return array(
|
||||||
'Remote' => '远程',
|
'Remote' => '远程',
|
||||||
'Enabled' => '启用',
|
'Enabled' => '启用',
|
||||||
'Disabled' => '停用',
|
'Disabled' => '停用',
|
||||||
'Google account linked' => '已经链接谷歌账号',
|
|
||||||
'Github account linked' => '已经链接Github账号',
|
|
||||||
'Username:' => '用户名:',
|
'Username:' => '用户名:',
|
||||||
'Name:' => '姓名:',
|
'Name:' => '姓名:',
|
||||||
'Email:' => '电子邮件:',
|
'Email:' => '电子邮件:',
|
||||||
|
@ -667,75 +665,26 @@ return array(
|
||||||
'Horizontal scrolling' => '水平滚动',
|
'Horizontal scrolling' => '水平滚动',
|
||||||
'Compact/wide view' => '紧凑/宽视图',
|
'Compact/wide view' => '紧凑/宽视图',
|
||||||
'No results match:' => '无匹配结果:',
|
'No results match:' => '无匹配结果:',
|
||||||
'Remove hourly rate' => '删除小时工资',
|
|
||||||
'Do you really want to remove this hourly rate?' => '确定要删除此计时工资吗?',
|
|
||||||
'Hourly rates' => '小时工资',
|
|
||||||
'Hourly rate' => '小时工资',
|
|
||||||
'Currency' => '货币',
|
'Currency' => '货币',
|
||||||
'Effective date' => '开始时间',
|
|
||||||
'Add new rate' => '添加小时工资',
|
|
||||||
'Rate removed successfully.' => '成功删除工资。',
|
|
||||||
'Unable to remove this rate.' => '无法删除此小时工资。',
|
|
||||||
'Unable to save the hourly rate.' => '无法删除小时工资。',
|
|
||||||
'Hourly rate created successfully.' => '成功创建小时工资。',
|
|
||||||
'Start time' => '开始时间',
|
|
||||||
'End time' => '结束时1间',
|
|
||||||
'Comment' => '注释',
|
|
||||||
'All day' => '全天',
|
|
||||||
'Day' => '日期',
|
|
||||||
'Manage timetable' => '管理时间表',
|
|
||||||
// 'Overtime timetable' => '',
|
|
||||||
'Time off timetable' => '加班时间表',
|
|
||||||
'Timetable' => '时间表',
|
|
||||||
'Work timetable' => '工作时间表',
|
|
||||||
'Week timetable' => '周时间表',
|
|
||||||
'Day timetable' => '日时间表',
|
|
||||||
'From' => '从',
|
|
||||||
'To' => '到',
|
|
||||||
'Time slot created successfully.' => '成功创建时间段。',
|
|
||||||
'Unable to save this time slot.' => '无法保存此时间段。',
|
|
||||||
'Time slot removed successfully.' => '成功删除时间段。',
|
|
||||||
'Unable to remove this time slot.' => '无法删除此时间段。',
|
|
||||||
'Do you really want to remove this time slot?' => '确认要删除此时间段吗?',
|
|
||||||
'Remove time slot' => '删除时间段',
|
|
||||||
'Add new time slot' => '添加新时间段',
|
|
||||||
'This timetable is used when the checkbox "all day" is checked for scheduled time off and overtime.' => '如果在放假和加班计划中选择全天,则会使用这里配置的时间段。',
|
|
||||||
'Files' => '文件',
|
'Files' => '文件',
|
||||||
'Images' => '图片',
|
'Images' => '图片',
|
||||||
'Private project' => '私人项目',
|
'Private project' => '私人项目',
|
||||||
'Amount' => '数量',
|
|
||||||
// 'AUD - Australian Dollar' => '',
|
// 'AUD - Australian Dollar' => '',
|
||||||
'Budget' => '预算',
|
|
||||||
'Budget line' => '预算线',
|
|
||||||
'Budget line removed successfully.' => '成功删除预算线',
|
|
||||||
'Budget lines' => '预算线',
|
|
||||||
// 'CAD - Canadian Dollar' => '',
|
// 'CAD - Canadian Dollar' => '',
|
||||||
// 'CHF - Swiss Francs' => '',
|
// 'CHF - Swiss Francs' => '',
|
||||||
'Cost' => '成本',
|
|
||||||
'Cost breakdown' => '成本分解',
|
|
||||||
'Custom Stylesheet' => '自定义样式表',
|
'Custom Stylesheet' => '自定义样式表',
|
||||||
'download' => '下载',
|
'download' => '下载',
|
||||||
'Do you really want to remove this budget line?' => '确定要删除此预算线吗?',
|
|
||||||
// 'EUR - Euro' => '',
|
// 'EUR - Euro' => '',
|
||||||
'Expenses' => '花费',
|
|
||||||
// 'GBP - British Pound' => '',
|
// 'GBP - British Pound' => '',
|
||||||
// 'INR - Indian Rupee' => '',
|
// 'INR - Indian Rupee' => '',
|
||||||
// 'JPY - Japanese Yen' => '',
|
// 'JPY - Japanese Yen' => '',
|
||||||
'New budget line' => '新预算线',
|
|
||||||
// 'NZD - New Zealand Dollar' => '',
|
// 'NZD - New Zealand Dollar' => '',
|
||||||
'Remove a budget line' => '删除预算线',
|
|
||||||
'Remove budget line' => '删除预算线',
|
|
||||||
// 'RSD - Serbian dinar' => '',
|
// 'RSD - Serbian dinar' => '',
|
||||||
'The budget line have been created successfully.' => '成功创建预算线。',
|
|
||||||
'Unable to create the budget line.' => '无法创建预算线。',
|
|
||||||
'Unable to remove this budget line.' => '无法删除此预算线。',
|
|
||||||
// 'USD - US Dollar' => '',
|
// 'USD - US Dollar' => '',
|
||||||
'Remaining' => '剩余',
|
|
||||||
'Destination column' => '目标栏目',
|
'Destination column' => '目标栏目',
|
||||||
'Move the task to another column when assigned to a user' => '指定负责人时移动到其它栏目',
|
'Move the task to another column when assigned to a user' => '指定负责人时移动到其它栏目',
|
||||||
'Move the task to another column when assignee is cleared' => '移除负责人时移动到其它栏目',
|
'Move the task to another column when assignee is cleared' => '移除负责人时移动到其它栏目',
|
||||||
'Source column' => '原栏目',
|
'Source column' => '原栏目',
|
||||||
// 'Show subtask estimates (forecast of future work)' => '',
|
|
||||||
'Transitions' => '变更',
|
'Transitions' => '变更',
|
||||||
'Executer' => '执行者',
|
'Executer' => '执行者',
|
||||||
'Time spent in the column' => '栏目中的时间消耗',
|
'Time spent in the column' => '栏目中的时间消耗',
|
||||||
|
@ -746,7 +695,6 @@ return array(
|
||||||
'Rate' => '汇率',
|
'Rate' => '汇率',
|
||||||
'Change reference currency' => '修改参考货币',
|
'Change reference currency' => '修改参考货币',
|
||||||
'Add a new currency rate' => '添加新汇率',
|
'Add a new currency rate' => '添加新汇率',
|
||||||
'Currency rates are used to calculate project budget.' => '汇率会用来计算项目预算。',
|
|
||||||
'Reference currency' => '参考货币',
|
'Reference currency' => '参考货币',
|
||||||
'The currency rate have been added successfully.' => '成功添加汇率。',
|
'The currency rate have been added successfully.' => '成功添加汇率。',
|
||||||
'Unable to add this currency rate.' => '无法添加此汇率',
|
'Unable to add this currency rate.' => '无法添加此汇率',
|
||||||
|
@ -878,9 +826,6 @@ return array(
|
||||||
// '%s moved the task #%d to the first swimlane' => '',
|
// '%s moved the task #%d to the first swimlane' => '',
|
||||||
// '%s moved the task #%d to the swimlane "%s"' => '',
|
// '%s moved the task #%d to the swimlane "%s"' => '',
|
||||||
// 'Swimlane' => '',
|
// 'Swimlane' => '',
|
||||||
'Budget overview' => '预算概览',
|
|
||||||
'Type' => '类型',
|
|
||||||
// 'There is not enough data to show something.' => '',
|
|
||||||
// 'Gravatar' => '',
|
// 'Gravatar' => '',
|
||||||
// 'Hipchat' => '',
|
// 'Hipchat' => '',
|
||||||
// 'Slack' => '',
|
// 'Slack' => '',
|
||||||
|
@ -1067,4 +1012,48 @@ return array(
|
||||||
// 'Table of contents' => '',
|
// 'Table of contents' => '',
|
||||||
// 'Gantt' => '',
|
// 'Gantt' => '',
|
||||||
// 'Help with project permissions' => '',
|
// 'Help with project permissions' => '',
|
||||||
|
// 'Author' => '',
|
||||||
|
// 'Version' => '',
|
||||||
|
// 'Plugins' => '',
|
||||||
|
// 'There is no plugin loaded.' => '',
|
||||||
|
// 'Set maximum column height' => '',
|
||||||
|
// 'Remove maximum column height' => '',
|
||||||
|
// 'My notifications' => '',
|
||||||
|
// 'Custom filters' => '',
|
||||||
|
// 'Your custom filter have been created successfully.' => '',
|
||||||
|
// 'Unable to create your custom filter.' => '',
|
||||||
|
// 'Custom filter removed successfully.' => '',
|
||||||
|
// 'Unable to remove this custom filter.' => '',
|
||||||
|
// 'Edit custom filter' => '',
|
||||||
|
// 'Your custom filter have been updated successfully.' => '',
|
||||||
|
// 'Unable to update custom filter.' => '',
|
||||||
|
// 'Web' => '',
|
||||||
|
// 'New attachment on task #%d: %s' => '',
|
||||||
|
// 'New comment on task #%d' => '',
|
||||||
|
// 'Comment updated on task #%d' => '',
|
||||||
|
// 'New subtask on task #%d' => '',
|
||||||
|
// 'Subtask updated on task #%d' => '',
|
||||||
|
// 'New task #%d: %s' => '',
|
||||||
|
// 'Task updated #%d' => '',
|
||||||
|
// 'Task #%d closed' => '',
|
||||||
|
// 'Task #%d opened' => '',
|
||||||
|
// 'Column changed for task #%d' => '',
|
||||||
|
// 'New position for task #%d' => '',
|
||||||
|
// 'Swimlane changed for task #%d' => '',
|
||||||
|
// 'Assignee changed on task #%d' => '',
|
||||||
|
// '%d overdue tasks' => '',
|
||||||
|
// 'Task #%d is overdue' => '',
|
||||||
|
// 'No new notifications.' => '',
|
||||||
|
// 'Mark all as read' => '',
|
||||||
|
// 'Mark as read' => '',
|
||||||
|
// 'Total number of tasks in this column across all swimlanes' => '',
|
||||||
|
// 'Collapse swimlane' => '',
|
||||||
|
// 'Expand swimlane' => '',
|
||||||
|
// 'Add a new filter' => '',
|
||||||
|
// 'Share with all project members' => '',
|
||||||
|
// 'Shared' => '',
|
||||||
|
// 'Owner' => '',
|
||||||
|
// 'Unread notifications' => '',
|
||||||
|
// 'My filters' => '',
|
||||||
|
// 'Notification methods:' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -47,6 +47,7 @@ class Acl extends Base
|
||||||
'taskstatus' => '*',
|
'taskstatus' => '*',
|
||||||
'tasklink' => '*',
|
'tasklink' => '*',
|
||||||
'timer' => '*',
|
'timer' => '*',
|
||||||
|
'customfilter' => '*',
|
||||||
'calendar' => array('show', 'project'),
|
'calendar' => array('show', 'project'),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -64,7 +65,6 @@ class Acl extends Base
|
||||||
'export' => '*',
|
'export' => '*',
|
||||||
'project' => array('edit', 'update', 'share', 'integration', 'users', 'alloweverybody', 'allow', 'setowner', 'revoke', 'duplicate', 'disable', 'enable'),
|
'project' => array('edit', 'update', 'share', 'integration', 'users', 'alloweverybody', 'allow', 'setowner', 'revoke', 'duplicate', 'disable', 'enable'),
|
||||||
'swimlane' => '*',
|
'swimlane' => '*',
|
||||||
'budget' => '*',
|
|
||||||
'gantt' => array('project', 'savetaskdate', 'task', 'savetask'),
|
'gantt' => array('project', 'savetaskdate', 'task', 'savetask'),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -94,6 +94,18 @@ class Acl extends Base
|
||||||
'twofactor' => array('disable'),
|
'twofactor' => array('disable'),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extend ACL rules
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $acl_name
|
||||||
|
* @param aray $rules
|
||||||
|
*/
|
||||||
|
public function extend($acl_name, array $rules)
|
||||||
|
{
|
||||||
|
$this->$acl_name = array_merge($this->$acl_name, $rules);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true if the specified controller/action match the given acl
|
* Return true if the specified controller/action match the given acl
|
||||||
*
|
*
|
||||||
|
|
|
@ -30,6 +30,28 @@ class Action extends Base
|
||||||
*/
|
*/
|
||||||
const TABLE_PARAMS = 'action_has_params';
|
const TABLE_PARAMS = 'action_has_params';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extended actions
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $actions = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extend the list of default actions
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $className
|
||||||
|
* @param string $description
|
||||||
|
* @return Action
|
||||||
|
*/
|
||||||
|
public function extendActions($className, $description)
|
||||||
|
{
|
||||||
|
$this->actions[$className] = $description;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the name and description of available actions
|
* Return the name and description of available actions
|
||||||
*
|
*
|
||||||
|
@ -62,6 +84,8 @@ class Action extends Base
|
||||||
'TaskAssignColorLink' => t('Change task color when using a specific task link'),
|
'TaskAssignColorLink' => t('Change task color when using a specific task link'),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$values = array_merge($values, $this->actions);
|
||||||
|
|
||||||
asort($values);
|
asort($values);
|
||||||
|
|
||||||
return $values;
|
return $values;
|
||||||
|
@ -296,7 +320,7 @@ class Action extends Base
|
||||||
*/
|
*/
|
||||||
public function load($name, $project_id, $event)
|
public function load($name, $project_id, $event)
|
||||||
{
|
{
|
||||||
$className = '\Action\\'.$name;
|
$className = $name{0} !== '\\' ? '\Action\\'.$name : $name;
|
||||||
return new $className($this->container, $project_id, $event);
|
return new $className($this->container, $project_id, $event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,26 +12,6 @@ use Pimple\Container;
|
||||||
*/
|
*/
|
||||||
abstract class Base extends \Core\Base
|
abstract class Base extends \Core\Base
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Database instance
|
|
||||||
*
|
|
||||||
* @access protected
|
|
||||||
* @var \PicoDb\Database
|
|
||||||
*/
|
|
||||||
protected $db;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param \Pimple\Container $container
|
|
||||||
*/
|
|
||||||
public function __construct(Container $container)
|
|
||||||
{
|
|
||||||
$this->container = $container;
|
|
||||||
$this->db = $this->container['db'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save a record in the database
|
* Save a record in the database
|
||||||
*
|
*
|
||||||
|
@ -62,14 +42,30 @@ abstract class Base extends \Core\Base
|
||||||
public function removeFields(array &$values, array $keys)
|
public function removeFields(array &$values, array $keys)
|
||||||
{
|
{
|
||||||
foreach ($keys as $key) {
|
foreach ($keys as $key) {
|
||||||
if (isset($values[$key])) {
|
if (array_key_exists($key, $values)) {
|
||||||
unset($values[$key]);
|
unset($values[$key]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Force some fields to be at 0 if empty
|
* Remove keys from an array if empty
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $values Input array
|
||||||
|
* @param string[] $keys List of keys to remove
|
||||||
|
*/
|
||||||
|
public function removeEmptyFields(array &$values, array $keys)
|
||||||
|
{
|
||||||
|
foreach ($keys as $key) {
|
||||||
|
if (array_key_exists($key, $values) && empty($values[$key])) {
|
||||||
|
unset($values[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force fields to be at 0 if empty
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @param array $values Input array
|
* @param array $values Input array
|
||||||
|
@ -100,6 +96,22 @@ abstract class Base extends \Core\Base
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force some fields to be null if empty
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $values Input array
|
||||||
|
* @param string[] $keys List of keys
|
||||||
|
*/
|
||||||
|
public function convertNullFields(array &$values, array $keys)
|
||||||
|
{
|
||||||
|
foreach ($keys as $key) {
|
||||||
|
if (array_key_exists($key, $values) && empty($values[$key])) {
|
||||||
|
$values[$key] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build SQL condition for a given time range
|
* Build SQL condition for a given time range
|
||||||
*
|
*
|
||||||
|
@ -124,26 +136,6 @@ abstract class Base extends \Core\Base
|
||||||
return $start_column.' IS NOT NULL AND '.$start_column.' > 0 AND ('.implode(' OR ', $conditions).')';
|
return $start_column.' IS NOT NULL AND '.$start_column.' > 0 AND ('.implode(' OR ', $conditions).')';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get common properties for task calendar events
|
|
||||||
*
|
|
||||||
* @access protected
|
|
||||||
* @param array $task
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
protected function getTaskCalendarProperties(array &$task)
|
|
||||||
{
|
|
||||||
return array(
|
|
||||||
'timezoneParam' => $this->config->getCurrentTimezone(),
|
|
||||||
'id' => $task['id'],
|
|
||||||
'title' => t('#%d', $task['id']).' '.$task['title'],
|
|
||||||
'backgroundColor' => $this->color->getBackgroundColor($task['color_id']),
|
|
||||||
'borderColor' => $this->color->getBorderColor($task['color_id']),
|
|
||||||
'textColor' => 'black',
|
|
||||||
'url' => $this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Group a collection of records by a column
|
* Group a collection of records by a column
|
||||||
*
|
*
|
||||||
|
|
|
@ -252,16 +252,24 @@ class Board extends Base
|
||||||
$swimlanes[$i]['columns'] = $columns;
|
$swimlanes[$i]['columns'] = $columns;
|
||||||
$swimlanes[$i]['nb_columns'] = $nb_columns;
|
$swimlanes[$i]['nb_columns'] = $nb_columns;
|
||||||
$swimlanes[$i]['nb_tasks'] = 0;
|
$swimlanes[$i]['nb_tasks'] = 0;
|
||||||
|
$swimlanes[$i]['nb_swimlanes'] = $ilen;
|
||||||
|
|
||||||
for ($j = 0; $j < $nb_columns; $j++) {
|
for ($j = 0; $j < $nb_columns; $j++) {
|
||||||
|
|
||||||
$column_id = $columns[$j]['id'];
|
$column_id = $columns[$j]['id'];
|
||||||
$swimlane_id = $swimlanes[$i]['id'];
|
$swimlane_id = $swimlanes[$i]['id'];
|
||||||
|
|
||||||
|
if (! isset($swimlanes[0]['columns'][$j]['nb_column_tasks'])) {
|
||||||
|
$swimlanes[0]['columns'][$j]['nb_column_tasks'] = 0;
|
||||||
|
$swimlanes[0]['columns'][$j]['total_score'] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
$swimlanes[$i]['columns'][$j]['tasks'] = $callback === null ? $this->taskFinder->getTasksByColumnAndSwimlane($project_id, $column_id, $swimlane_id) : $callback($project_id, $column_id, $swimlane_id);
|
$swimlanes[$i]['columns'][$j]['tasks'] = $callback === null ? $this->taskFinder->getTasksByColumnAndSwimlane($project_id, $column_id, $swimlane_id) : $callback($project_id, $column_id, $swimlane_id);
|
||||||
$swimlanes[$i]['columns'][$j]['nb_tasks'] = count($swimlanes[$i]['columns'][$j]['tasks']);
|
$swimlanes[$i]['columns'][$j]['nb_tasks'] = count($swimlanes[$i]['columns'][$j]['tasks']);
|
||||||
$swimlanes[$i]['columns'][$j]['score'] = $this->getColumnSum($swimlanes[$i]['columns'][$j]['tasks'], 'score');
|
$swimlanes[$i]['columns'][$j]['score'] = $this->getColumnSum($swimlanes[$i]['columns'][$j]['tasks'], 'score');
|
||||||
$swimlanes[$i]['nb_tasks'] += $swimlanes[$i]['columns'][$j]['nb_tasks'];
|
$swimlanes[$i]['nb_tasks'] += $swimlanes[$i]['columns'][$j]['nb_tasks'];
|
||||||
|
$swimlanes[0]['columns'][$j]['nb_column_tasks'] += $swimlanes[$i]['columns'][$j]['nb_tasks'];
|
||||||
|
$swimlanes[0]['columns'][$j]['total_score'] += $swimlanes[$i]['columns'][$j]['score'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -394,6 +402,18 @@ class Board extends Base
|
||||||
return (int) $this->db->table(self::TABLE)->eq('project_id', $project_id)->eq('title', $title)->findOneColumn('id');
|
return (int) $this->db->table(self::TABLE)->eq('project_id', $project_id)->eq('title', $title)->findOneColumn('id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a column title by the id
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $column_id
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public function getColumnTitleById($column_id)
|
||||||
|
{
|
||||||
|
return $this->db->table(self::TABLE)->eq('id', $column_id)->findOneColumn('title');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the position of the last column for a given project
|
* Get the position of the last column for a given project
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,214 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Model;
|
|
||||||
|
|
||||||
use DateInterval;
|
|
||||||
use DateTime;
|
|
||||||
use SimpleValidator\Validator;
|
|
||||||
use SimpleValidator\Validators;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Budget
|
|
||||||
*
|
|
||||||
* @package model
|
|
||||||
* @author Frederic Guillot
|
|
||||||
*/
|
|
||||||
class Budget extends Base
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* SQL table name
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
const TABLE = 'budget_lines';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all budget lines for a project
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param integer $project_id
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function getAll($project_id)
|
|
||||||
{
|
|
||||||
return $this->db->table(self::TABLE)->eq('project_id', $project_id)->desc('date')->findAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the current total of the budget
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param integer $project_id
|
|
||||||
* @return float
|
|
||||||
*/
|
|
||||||
public function getTotal($project_id)
|
|
||||||
{
|
|
||||||
$result = $this->db->table(self::TABLE)->columns('SUM(amount) as total')->eq('project_id', $project_id)->findOne();
|
|
||||||
return isset($result['total']) ? (float) $result['total'] : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get breakdown by tasks/subtasks/users
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param integer $project_id
|
|
||||||
* @return \PicoDb\Table
|
|
||||||
*/
|
|
||||||
public function getSubtaskBreakdown($project_id)
|
|
||||||
{
|
|
||||||
return $this->db
|
|
||||||
->table(SubtaskTimeTracking::TABLE)
|
|
||||||
->columns(
|
|
||||||
SubtaskTimeTracking::TABLE.'.id',
|
|
||||||
SubtaskTimeTracking::TABLE.'.user_id',
|
|
||||||
SubtaskTimeTracking::TABLE.'.subtask_id',
|
|
||||||
SubtaskTimeTracking::TABLE.'.start',
|
|
||||||
SubtaskTimeTracking::TABLE.'.time_spent',
|
|
||||||
Subtask::TABLE.'.task_id',
|
|
||||||
Subtask::TABLE.'.title AS subtask_title',
|
|
||||||
Task::TABLE.'.title AS task_title',
|
|
||||||
Task::TABLE.'.project_id',
|
|
||||||
User::TABLE.'.username',
|
|
||||||
User::TABLE.'.name'
|
|
||||||
)
|
|
||||||
->join(Subtask::TABLE, 'id', 'subtask_id')
|
|
||||||
->join(Task::TABLE, 'id', 'task_id', Subtask::TABLE)
|
|
||||||
->join(User::TABLE, 'id', 'user_id')
|
|
||||||
->eq(Task::TABLE.'.project_id', $project_id)
|
|
||||||
->callback(array($this, 'applyUserRate'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gather necessary information to display the budget graph
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param integer $project_id
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function getDailyBudgetBreakdown($project_id)
|
|
||||||
{
|
|
||||||
$out = array();
|
|
||||||
$in = $this->db->hashtable(self::TABLE)->eq('project_id', $project_id)->gt('amount', 0)->asc('date')->getAll('date', 'amount');
|
|
||||||
$time_slots = $this->getSubtaskBreakdown($project_id)->findAll();
|
|
||||||
|
|
||||||
foreach ($time_slots as $slot) {
|
|
||||||
$date = date('Y-m-d', $slot['start']);
|
|
||||||
|
|
||||||
if (! isset($out[$date])) {
|
|
||||||
$out[$date] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
$out[$date] += $slot['cost'];
|
|
||||||
}
|
|
||||||
|
|
||||||
$start = key($in) ?: key($out);
|
|
||||||
$end = new DateTime;
|
|
||||||
$left = 0;
|
|
||||||
$serie = array();
|
|
||||||
|
|
||||||
for ($today = new DateTime($start); $today <= $end; $today->add(new DateInterval('P1D'))) {
|
|
||||||
|
|
||||||
$date = $today->format('Y-m-d');
|
|
||||||
$today_in = isset($in[$date]) ? (int) $in[$date] : 0;
|
|
||||||
$today_out = isset($out[$date]) ? (int) $out[$date] : 0;
|
|
||||||
|
|
||||||
if ($today_in > 0 || $today_out > 0) {
|
|
||||||
|
|
||||||
$left += $today_in;
|
|
||||||
$left -= $today_out;
|
|
||||||
|
|
||||||
$serie[] = array(
|
|
||||||
'date' => $date,
|
|
||||||
'in' => $today_in,
|
|
||||||
'out' => -$today_out,
|
|
||||||
'left' => $left,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $serie;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Filter callback to apply the rate according to the effective date
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param array $records
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function applyUserRate(array $records)
|
|
||||||
{
|
|
||||||
$rates = $this->hourlyRate->getAllByProject($records[0]['project_id']);
|
|
||||||
|
|
||||||
foreach ($records as &$record) {
|
|
||||||
|
|
||||||
$hourly_price = 0;
|
|
||||||
|
|
||||||
foreach ($rates as $rate) {
|
|
||||||
|
|
||||||
if ($rate['user_id'] == $record['user_id'] && date('Y-m-d', $rate['date_effective']) <= date('Y-m-d', $record['start'])) {
|
|
||||||
$hourly_price = $this->currency->getPrice($rate['currency'], $rate['rate']);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$record['cost'] = $hourly_price * $record['time_spent'];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $records;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a new budget line in the database
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param integer $project_id
|
|
||||||
* @param float $amount
|
|
||||||
* @param string $comment
|
|
||||||
* @param string $date
|
|
||||||
* @return boolean|integer
|
|
||||||
*/
|
|
||||||
public function create($project_id, $amount, $comment, $date = '')
|
|
||||||
{
|
|
||||||
$values = array(
|
|
||||||
'project_id' => $project_id,
|
|
||||||
'amount' => $amount,
|
|
||||||
'comment' => $comment,
|
|
||||||
'date' => $date ?: date('Y-m-d'),
|
|
||||||
);
|
|
||||||
|
|
||||||
return $this->persist(self::TABLE, $values);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a specific budget line
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param integer $budget_id
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public function remove($budget_id)
|
|
||||||
{
|
|
||||||
return $this->db->table(self::TABLE)->eq('id', $budget_id)->remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate creation
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param array $values Form values
|
|
||||||
* @return array $valid, $errors [0] = Success or not, [1] = List of errors
|
|
||||||
*/
|
|
||||||
public function validateCreation(array $values)
|
|
||||||
{
|
|
||||||
$v = new Validator($values, array(
|
|
||||||
new Validators\Required('project_id', t('Field required')),
|
|
||||||
new Validators\Required('amount', t('Field required')),
|
|
||||||
));
|
|
||||||
|
|
||||||
return array(
|
|
||||||
$v->execute(),
|
|
||||||
$v->getErrors()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue