Merge branch 'master' into stable

stable
David Barragán Merino 2016-09-30 19:23:25 +02:00
commit 384df341e9
571 changed files with 23560 additions and 7014 deletions

3
.gitignore vendored
View File

@ -9,9 +9,10 @@ app/coffee/modules/locales/locale*.coffee
*.swp *.swp
*.swo *.swo
.#* .#*
tags /tags
tmp/ tmp/
app/config/main.coffee app/config/main.coffee
scss-lint.log scss-lint.log
e2e/screenshots/ e2e/screenshots/
e2e/reports/
app/modules/compile-modules/ app/modules/compile-modules/

View File

@ -26,8 +26,10 @@ answer newbie questions, and generally made Taiga that much better:
- Guilhem Got <guilhem.got@gmail.com> - Guilhem Got <guilhem.got@gmail.com>
- Jordan Rinke - Jordan Rinke
- Miguel de la Cruz <miguel.delacruz@kaleidos.net> - Miguel de la Cruz <miguel.delacruz@kaleidos.net>
- Mika Andrianarijaona <mikaoelitiana@gmail.com>
- Pilar Esteban <pilar.esteban@gmail.com> - Pilar Esteban <pilar.esteban@gmail.com>
- Ramiro Sánchez <ramiro.sanzhez@kaleidos.net> - Ramiro Sánchez <ramiro.sanzhez@kaleidos.net>
- Ryan Swanstrom - Ryan Swanstrom
- Vlad Topala <topalavlad@gmail.com> - Vlad Topala <topalavlad@gmail.com>
- Wil Wade - Wil Wade
- Iago Last

View File

@ -1,11 +1,42 @@
# Changelog # # Changelog #
## 2.2.0 ???? (Unreleased) ## 3.0.0 Stellaria Borealis (2016-10-02)
### Features ### Features
- Show a confirmation notice when you exit edit mode by pressing ESC in the markdown inputs. - Add Epics.
- Add the tribe button to link stories from tree.taiga.io with gigs in tribe.taiga.io. - Add the tribe button to link stories from tree.taiga.io with gigs in tribe.taiga.io.
- Show a confirmation notice when you exit edit mode by pressing ESC in the markdown inputs.
- Errors (not found, server error, permissions and blocked project) don't change the current url.
- Neew Attachments image slider in preview mode.
- New admin area to edit the tag colors used in your project.
- Set color when add a new tags to epics, stories, tasks or issues.
- Display the current user (me) at first in assignment lightbox (thanks to [@mikaoelitiana](https://github.com/mikaoelitiana))
- Divide the user dashboard in two columns in large screens.
- Upvote and downvote issues from the issues list.
- Show points per role in statsection of the taskboard panel. (thanks to [@fmartingr](https://github.com/fmartingr))
- Show a funny randon animals/color for users with no avatar (like project logos).
- Show Open Sprints in the left navigation menu (backlog submenu).
- Filters:
- Refactor the filter module.
- Add filters in the kanban panel.
- Add filter in the sprint taskboard panel.
- Cards UI improvements:
- Add zoom levels.
- Show information according the zoom level.
- Show voters, watchers, taks and attachments.
- Improve performance.
- Comments:
- Add a new permissions to allow add comments instead of use the existent modify permission for this purpose.
- Ability to edit comments, view edition history and redesign comments module UI.
- Wiki:
- Drag & Drop ordering for wiki links.
- Add a list of all wiki pages
- Add Wiki history
- Third party integrations:
- Included gogs as builtin integration.
- i18n:
- Add norwegian Bokmal (nb) translation.
### Misc ### Misc
- Lots of small and not so small bugfixes. - Lots of small and not so small bugfixes.

View File

@ -33,7 +33,7 @@ loadStylesheet = (path) ->
loadPlugin = (pluginPath) -> loadPlugin = (pluginPath) ->
return new Promise (resolve, reject) -> return new Promise (resolve, reject) ->
$.getJSON(pluginPath).then (plugin) -> success = (plugin) ->
window.taigaContribPlugins.push(plugin) window.taigaContribPlugins.push(plugin)
if plugin.css if plugin.css
@ -45,6 +45,11 @@ loadPlugin = (pluginPath) ->
else else
resolve() resolve()
fail = () ->
console.error("error loading", pluginPath);
$.getJSON(pluginPath).then(success, fail)
loadPlugins = (plugins) -> loadPlugins = (plugins) ->
promises = [] promises = []
_.map plugins, (pluginPath) -> _.map plugins, (pluginPath) ->

View File

@ -46,7 +46,7 @@ configure = ($routeProvider, $locationProvider, $httpProvider, $provide, $tgEven
$animateProvider.classNameFilter(/^(?:(?!ng-animate-disabled).)*$/) $animateProvider.classNameFilter(/^(?:(?!ng-animate-disabled).)*$/)
# wait until the trasnlation is ready to resolve the page # wait until the translation is ready to resolve the page
originalWhen = $routeProvider.when originalWhen = $routeProvider.when
$routeProvider.when = (path, route) -> $routeProvider.when = (path, route) ->
@ -57,12 +57,26 @@ configure = ($routeProvider, $locationProvider, $httpProvider, $provide, $tgEven
$translate().then () -> deferred.resolve() $translate().then () -> deferred.resolve()
return deferred.promise
],
projectLoaded: ["$q", "tgProjectService", "$route", ($q, projectService, $route) ->
deferred = $q.defer()
projectService.setSection($route.current.$$route?.section)
if $route.current.params.pslug
projectService.setProjectBySlug($route.current.params.pslug).then(deferred.resolve)
else
projectService.cleanProject()
deferred.resolve()
return deferred.promise return deferred.promise
] ]
}) })
return originalWhen.call($routeProvider, path, route) return originalWhen.call($routeProvider, path, route)
# Home
$routeProvider.when("/", $routeProvider.when("/",
{ {
templateUrl: "home/home.html", templateUrl: "home/home.html",
@ -76,6 +90,7 @@ configure = ($routeProvider, $locationProvider, $httpProvider, $provide, $tgEven
} }
) )
# Discover
$routeProvider.when("/discover", $routeProvider.when("/discover",
{ {
templateUrl: "discover/discover-home/discover-home.html", templateUrl: "discover/discover-home/discover-home.html",
@ -97,6 +112,7 @@ configure = ($routeProvider, $locationProvider, $httpProvider, $provide, $tgEven
} }
) )
# My Projects
$routeProvider.when("/projects/", $routeProvider.when("/projects/",
{ {
templateUrl: "projects/listing/projects-listing.html", templateUrl: "projects/listing/projects-listing.html",
@ -110,17 +126,7 @@ configure = ($routeProvider, $locationProvider, $httpProvider, $provide, $tgEven
controllerAs: "vm" controllerAs: "vm"
} }
) )
# Project
$routeProvider.when("/blocked-project/:pslug/",
{
templateUrl: "projects/project/blocked-project.html",
loader: true,
controller: "Project",
controllerAs: "vm"
}
)
$routeProvider.when("/project/:pslug/", $routeProvider.when("/project/:pslug/",
{ {
templateUrl: "projects/project/project.html", templateUrl: "projects/project/project.html",
@ -140,6 +146,25 @@ configure = ($routeProvider, $locationProvider, $httpProvider, $provide, $tgEven
} }
) )
# Epics
$routeProvider.when("/project/:pslug/epics",
{
section: "epics",
templateUrl: "epics/dashboard/epics-dashboard.html",
loader: true,
controller: "EpicsDashboardCtrl",
controllerAs: "vm"
}
)
$routeProvider.when("/project/:pslug/epic/:epicref",
{
templateUrl: "epic/epic-detail.html",
loader: true,
section: "epics"
}
)
$routeProvider.when("/project/:pslug/backlog", $routeProvider.when("/project/:pslug/backlog",
{ {
templateUrl: "backlog/backlog.html", templateUrl: "backlog/backlog.html",
@ -188,6 +213,13 @@ configure = ($routeProvider, $locationProvider, $httpProvider, $provide, $tgEven
# Wiki # Wiki
$routeProvider.when("/project/:pslug/wiki", $routeProvider.when("/project/:pslug/wiki",
{redirectTo: (params) -> "/project/#{params.pslug}/wiki/home"}, ) {redirectTo: (params) -> "/project/#{params.pslug}/wiki/home"}, )
$routeProvider.when("/project/:pslug/wiki-list",
{
templateUrl: "wiki/wiki-list.html",
loader: true,
section: "wiki"
}
)
$routeProvider.when("/project/:pslug/wiki/:slug", $routeProvider.when("/project/:pslug/wiki/:slug",
{ {
templateUrl: "wiki/wiki.html", templateUrl: "wiki/wiki.html",
@ -289,7 +321,12 @@ configure = ($routeProvider, $locationProvider, $httpProvider, $provide, $tgEven
section: "admin" section: "admin"
} }
) )
$routeProvider.when("/project/:pslug/admin/project-values/tags",
{
templateUrl: "admin/admin-project-values-tags.html",
section: "admin"
}
)
$routeProvider.when("/project/:pslug/admin/memberships", $routeProvider.when("/project/:pslug/admin/memberships",
{ {
templateUrl: "admin/admin-memberships.html", templateUrl: "admin/admin-memberships.html",
@ -329,6 +366,12 @@ configure = ($routeProvider, $locationProvider, $httpProvider, $provide, $tgEven
section: "admin" section: "admin"
} }
) )
$routeProvider.when("/project/:pslug/admin/third-parties/gogs",
{
templateUrl: "admin/admin-third-parties-gogs.html",
section: "admin"
}
)
# Admin - Contrib Plugins # Admin - Contrib Plugins
$routeProvider.when("/project/:pslug/admin/contrib/:plugin", $routeProvider.when("/project/:pslug/admin/contrib/:plugin",
{templateUrl: "contrib/main.html"}) {templateUrl: "contrib/main.html"})
@ -436,6 +479,12 @@ configure = ($routeProvider, $locationProvider, $httpProvider, $provide, $tgEven
) )
# Errors/Exceptions # Errors/Exceptions
$routeProvider.when("/blocked-project/:pslug/",
{
templateUrl: "projects/project/blocked-project.html",
loader: true,
}
)
$routeProvider.when("/error", $routeProvider.when("/error",
{templateUrl: "error/error.html"}) {templateUrl: "error/error.html"})
$routeProvider.when("/not-found", $routeProvider.when("/not-found",
@ -443,7 +492,7 @@ configure = ($routeProvider, $locationProvider, $httpProvider, $provide, $tgEven
$routeProvider.when("/permission-denied", $routeProvider.when("/permission-denied",
{templateUrl: "error/permission-denied.html"}) {templateUrl: "error/permission-denied.html"})
$routeProvider.otherwise({redirectTo: "/not-found"}) $routeProvider.otherwise({templateUrl: "error/not-found.html"})
$locationProvider.html5Mode({enabled: true, requireBase: false}) $locationProvider.html5Mode({enabled: true, requireBase: false})
defaultHeaders = { defaultHeaders = {
@ -465,15 +514,22 @@ configure = ($routeProvider, $locationProvider, $httpProvider, $provide, $tgEven
$tgEventsProvider.setSessionId(taiga.sessionId) $tgEventsProvider.setSessionId(taiga.sessionId)
# Add next param when user try to access to a secction need auth permissions. # Add next param when user try to access to a secction need auth permissions.
authHttpIntercept = ($q, $location, $navUrls, $lightboxService) -> authHttpIntercept = ($q, $location, $navUrls, $lightboxService, errorHandlingService) ->
httpResponseError = (response) -> httpResponseError = (response) ->
if response.status == 0 || (response.status == -1 && !response.config.cancelable) if response.status == 0 || (response.status == -1 && !response.config.cancelable)
$lightboxService.closeAll() $lightboxService.closeAll()
$location.path($navUrls.resolve("error"))
$location.replace() errorHandlingService.error()
else if response.status == 401 and $location.url().indexOf('/login') == -1 else if response.status == 401 and $location.url().indexOf('/login') == -1
nextUrl = encodeURIComponent($location.url()) nextUrl = $location.url()
$location.url($navUrls.resolve("login")).search("next=#{nextUrl}") search = $location.search()
if search.force_next
$location.url($navUrls.resolve("login"))
.search("force_next", search.force_next)
else
$location.url($navUrls.resolve("login"))
.search("next", nextUrl)
return $q.reject(response) return $q.reject(response)
@ -482,7 +538,7 @@ configure = ($routeProvider, $locationProvider, $httpProvider, $provide, $tgEven
} }
$provide.factory("authHttpIntercept", ["$q", "$location", "$tgNavUrls", "lightboxService", $provide.factory("authHttpIntercept", ["$q", "$location", "$tgNavUrls", "lightboxService",
authHttpIntercept]) "tgErrorHandlingService", authHttpIntercept])
$httpProvider.interceptors.push("authHttpIntercept") $httpProvider.interceptors.push("authHttpIntercept")
@ -536,18 +592,14 @@ configure = ($routeProvider, $locationProvider, $httpProvider, $provide, $tgEven
$httpProvider.interceptors.push("versionCheckHttpIntercept") $httpProvider.interceptors.push("versionCheckHttpIntercept")
blockingIntercept = ($q, $routeParams, $location, $navUrls) -> blockingIntercept = ($q, errorHandlingService) ->
# API calls can return blocked elements and in that situation the user will be redirected # API calls can return blocked elements and in that situation the user will be redirected
# to the blocked project page # to the blocked project page
# This can happens in two scenarios # This can happens in two scenarios
# - An ok response containing a blocked_code in the data # - An ok response containing a blocked_code in the data
# - An error reponse when updating/creating/deleting including a 451 error code # - An error reponse when updating/creating/deleting including a 451 error code
redirectToBlockedPage = -> redirectToBlockedPage = ->
pslug = $routeParams.pslug errorHandlingService.block()
blockedUrl = $navUrls.resolve("blocked-project", {project: pslug})
currentUrl = $location.url()
if currentUrl.indexOf(blockedUrl) == -1
$location.replace().path(blockedUrl)
responseOk = (response) -> responseOk = (response) ->
if response.data.blocked_code if response.data.blocked_code
@ -566,7 +618,7 @@ configure = ($routeProvider, $locationProvider, $httpProvider, $provide, $tgEven
responseError: responseError responseError: responseError
} }
$provide.factory("blockingIntercept", ["$q", "$routeParams", "$location", "$tgNavUrls", blockingIntercept]) $provide.factory("blockingIntercept", ["$q", "tgErrorHandlingService", blockingIntercept])
$httpProvider.interceptors.push("blockingIntercept") $httpProvider.interceptors.push("blockingIntercept")
@ -637,7 +689,8 @@ i18nInit = (lang, $translate) ->
checksley.updateMessages('default', messages) checksley.updateMessages('default', messages)
init = ($log, $rootscope, $auth, $events, $analytics, $translate, $location, $navUrls, appMetaService, projectService, loaderService, navigationBarService) -> init = ($log, $rootscope, $auth, $events, $analytics, $translate, $location, $navUrls, appMetaService,
loaderService, navigationBarService, errorHandlingService) ->
$log.debug("Initialize application") $log.debug("Initialize application")
$rootscope.$on '$translatePartialLoaderStructureChanged', () -> $rootscope.$on '$translatePartialLoaderStructureChanged', () ->
@ -680,6 +733,10 @@ init = ($log, $rootscope, $auth, $events, $analytics, $translate, $location, $na
# Analytics # Analytics
$analytics.initialize() $analytics.initialize()
# Initialize error handling service when location change start
$rootscope.$on '$locationChangeStart', (event) ->
errorHandlingService.init()
# On the first page load the loader is painted in `$routeChangeSuccess` # On the first page load the loader is painted in `$routeChangeSuccess`
# because we need to hide the tg-navigation-bar. # because we need to hide the tg-navigation-bar.
# In the other cases the loader is in `$routeChangeSuccess` # In the other cases the loader is in `$routeChangeSuccess`
@ -690,7 +747,7 @@ init = ($log, $rootscope, $auth, $events, $analytics, $translate, $location, $na
un() un()
$rootscope.$on '$routeChangeSuccess', (event, next) -> $rootscope.$on '$routeChangeSuccess', (event, next) ->
if next.loader if next.loader
loaderService.start(true) loaderService.start(true)
@ -698,13 +755,6 @@ init = ($log, $rootscope, $auth, $events, $analytics, $translate, $location, $na
if !$auth.isAuthenticated() if !$auth.isAuthenticated()
$location.path($navUrls.resolve("login")) $location.path($navUrls.resolve("login"))
projectService.setSection(next.section)
if next.params.pslug
projectService.setProjectBySlug(next.params.pslug)
else
projectService.cleanProject()
if next.title or next.description if next.title or next.description
title = $translate.instant(next.title or "") title = $translate.instant(next.title or "")
description = $translate.instant(next.description or "") description = $translate.instant(next.description or "")
@ -712,7 +762,7 @@ init = ($log, $rootscope, $auth, $events, $analytics, $translate, $location, $na
if next.mobileViewport if next.mobileViewport
appMetaService.addMobileViewport() appMetaService.addMobileViewport()
else else
appMetaService.removeMobileViewport() appMetaService.removeMobileViewport()
if next.disableHeader if next.disableHeader
@ -720,10 +770,13 @@ init = ($log, $rootscope, $auth, $events, $analytics, $translate, $location, $na
else else
navigationBarService.enableHeader() navigationBarService.enableHeader()
pluginsWithModule = _.filter(@.taigaContribPlugins, (plugin) -> plugin.module) # Config for infinite scroll
angular.module('infinite-scroll').value('THROTTLE_MILLISECONDS', 500) angular.module('infinite-scroll').value('THROTTLE_MILLISECONDS', 500)
# Load modules
pluginsWithModule = _.filter(@.taigaContribPlugins, (plugin) -> plugin.module)
pluginsModules = _.map(pluginsWithModule, (plugin) -> plugin.module)
modules = [ modules = [
# Main Global Modules # Main Global Modules
"taigaBase", "taigaBase",
@ -754,12 +807,17 @@ modules = [
"taigaPlugins", "taigaPlugins",
"taigaIntegrations", "taigaIntegrations",
"taigaComponents", "taigaComponents",
# new modules # new modules
"taigaProfile", "taigaProfile",
"taigaHome", "taigaHome",
"taigaUserTimeline", "taigaUserTimeline",
"taigaExternalApps", "taigaExternalApps",
"taigaDiscover", "taigaDiscover",
"taigaHistory",
"taigaWikiHistory",
"taigaEpics",
"taigaUtils"
# template cache # template cache
"templates", "templates",
@ -772,7 +830,7 @@ modules = [
"pascalprecht.translate", "pascalprecht.translate",
"infinite-scroll", "infinite-scroll",
"tgRepeat" "tgRepeat"
].concat(_.map(pluginsWithModule, (plugin) -> plugin.module)) ].concat(pluginsModules)
# Main module definition # Main module definition
module = angular.module("taiga", modules) module = angular.module("taiga", modules)
@ -800,9 +858,8 @@ module.run([
"$tgLocation", "$tgLocation",
"$tgNavUrls", "$tgNavUrls",
"tgAppMetaService", "tgAppMetaService",
"tgProjectService",
"tgLoader", "tgLoader",
"tgNavigationBarService", "tgNavigationBarService",
"$route", "tgErrorHandlingService",
init init
]) ])

View File

@ -28,11 +28,9 @@ class TaigaController extends TaigaBase
onInitialDataError: (xhr) => onInitialDataError: (xhr) =>
if xhr if xhr
if xhr.status == 404 if xhr.status == 404
@location.path(@navUrls.resolve("not-found")) @errorHandlingService.notfound()
@location.replace()
else if xhr.status == 403 else if xhr.status == 403
@location.path(@navUrls.resolve("permission-denied")) @errorHandlingService.permissionDenied()
@location.replace()
return @q.reject(xhr) return @q.reject(xhr)

View File

@ -99,7 +99,14 @@ class LightboxAddMembersController
_onErrorInvite: (response) -> _onErrorInvite: (response) ->
@.submitInvites = false @.submitInvites = false
@.form.setErrors(response.data) errors = {}
_.each response.data.bulk_memberships, (value, index) =>
if value.email
errors["email-#{index}"] = value.email[0]
if value.role
errors["role-#{index}"] = value.role[0]
@.form.setErrors(errors)
if response.data._error_message if response.data._error_message
@confirm.notify("error", response.data._error_message) @confirm.notify("error", response.data._error_message)

View File

@ -48,12 +48,13 @@ class MembershipsController extends mixOf(taiga.Controller, taiga.PageMixin, tai
"$tgAnalytics", "$tgAnalytics",
"tgAppMetaService", "tgAppMetaService",
"$translate", "$translate",
"$tgAuth" "$tgAuth",
"tgLightboxFactory" "tgLightboxFactory",
"tgErrorHandlingService"
] ]
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, @navUrls, @analytics, constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, @navUrls, @analytics,
@appMetaService, @translate, @auth, @lightboxFactory) -> @appMetaService, @translate, @auth, @lightboxFactory, @errorHandlingService) ->
bindMethods(@) bindMethods(@)
@scope.project = {} @scope.project = {}
@ -75,7 +76,7 @@ class MembershipsController extends mixOf(taiga.Controller, taiga.PageMixin, tai
loadProject: -> loadProject: ->
return @rs.projects.getBySlug(@params.pslug).then (project) => return @rs.projects.getBySlug(@params.pslug).then (project) =>
if not project.i_am_admin if not project.i_am_admin
@location.path(@navUrls.resolve("permission-denied")) @errorHandlingService.permissionDenied()
@scope.projectId = project.id @scope.projectId = project.id
@scope.project = project @scope.project = project
@ -240,16 +241,19 @@ module.directive("tgMemberships", ["$tgTemplate", "$compile", MembershipsDirecti
## Member Avatar Directive ## Member Avatar Directive
############################################################################# #############################################################################
MembershipsRowAvatarDirective = ($log, $template, $translate, $compile) -> MembershipsRowAvatarDirective = ($log, $template, $translate, $compile, avatarService) ->
template = $template.get("admin/memberships-row-avatar.html", true) template = $template.get("admin/memberships-row-avatar.html", true)
link = ($scope, $el, $attrs) -> link = ($scope, $el, $attrs) ->
pending = $translate.instant("ADMIN.MEMBERSHIP.STATUS_PENDING") pending = $translate.instant("ADMIN.MEMBERSHIP.STATUS_PENDING")
render = (member) -> render = (member) ->
avatar = avatarService.getAvatar(member)
ctx = { ctx = {
full_name: if member.full_name then member.full_name else "" full_name: if member.full_name then member.full_name else ""
email: if member.user_email then member.user_email else member.email email: if member.user_email then member.user_email else member.email
imgurl: if member.photo then member.photo else "/" + window._version + "/images/unnamed.png" imgurl: avatar.url
bg: avatar.bg
pending: if !member.is_user_active then pending else "" pending: if !member.is_user_active then pending else ""
isOwner: member.is_owner isOwner: member.is_owner
} }
@ -271,7 +275,7 @@ MembershipsRowAvatarDirective = ($log, $template, $translate, $compile) ->
return {link: link} return {link: link}
module.directive("tgMembershipsRowAvatar", ["$log", "$tgTemplate", '$translate', "$compile", MembershipsRowAvatarDirective]) module.directive("tgMembershipsRowAvatar", ["$log", "$tgTemplate", '$translate', "$compile", "tgAvatarService", MembershipsRowAvatarDirective])
############################################################################# #############################################################################

View File

@ -53,14 +53,16 @@ class ProjectProfileController extends mixOf(taiga.Controller, taiga.PageMixin)
"tgAppMetaService", "tgAppMetaService",
"$translate", "$translate",
"$tgAuth", "$tgAuth",
"tgCurrentUserService" "tgCurrentUserService",
"tgErrorHandlingService"
] ]
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, @navUrls, constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, @navUrls,
@appMetaService, @translate, @tgAuth, @currentUserService) -> @appMetaService, @translate, @tgAuth, @currentUserService, @errorHandlingService) ->
@scope.project = {} @scope.project = {}
promise = @.loadInitialData() promise = @.loadInitialData()
@scope.projectTags = []
promise.then => promise.then =>
sectionName = @translate.instant( @scope.sectionName) sectionName = @translate.instant( @scope.sectionName)
@ -83,18 +85,23 @@ class ProjectProfileController extends mixOf(taiga.Controller, taiga.PageMixin)
loadProject: -> loadProject: ->
return @rs.projects.getBySlug(@params.pslug).then (project) => return @rs.projects.getBySlug(@params.pslug).then (project) =>
if not project.i_am_admin if not project.i_am_admin
@location.path(@navUrls.resolve("permission-denied")) @errorHandlingService.permissionDenied()
@scope.projectId = project.id @scope.projectId = project.id
@scope.project = project @scope.project = project
@scope.pointsList = _.sortBy(project.points, "order") @scope.epicStatusList = _.sortBy(project.epic_statuses, "order")
@scope.usStatusList = _.sortBy(project.us_statuses, "order") @scope.usStatusList = _.sortBy(project.us_statuses, "order")
@scope.pointsList = _.sortBy(project.points, "order")
@scope.taskStatusList = _.sortBy(project.task_statuses, "order") @scope.taskStatusList = _.sortBy(project.task_statuses, "order")
@scope.prioritiesList = _.sortBy(project.priorities, "order")
@scope.severitiesList = _.sortBy(project.severities, "order")
@scope.issueTypesList = _.sortBy(project.issue_types, "order") @scope.issueTypesList = _.sortBy(project.issue_types, "order")
@scope.issueStatusList = _.sortBy(project.issue_statuses, "order") @scope.issueStatusList = _.sortBy(project.issue_statuses, "order")
@scope.prioritiesList = _.sortBy(project.priorities, "order")
@scope.severitiesList = _.sortBy(project.severities, "order")
@scope.$emit('project:loaded', project) @scope.$emit('project:loaded', project)
@scope.projectTags = _.map @scope.project.tags, (it) =>
return [it, @scope.project.tags_colors[it]]
return project return project
loadInitialData: -> loadInitialData: ->
@ -106,6 +113,21 @@ class ProjectProfileController extends mixOf(taiga.Controller, taiga.PageMixin)
openDeleteLightbox: -> openDeleteLightbox: ->
@rootscope.$broadcast("deletelightbox:new", @scope.project) @rootscope.$broadcast("deletelightbox:new", @scope.project)
addTag: (name, color) ->
tags = _.clone(@scope.project.tags)
tags.push(name)
@scope.projectTags.push([name, null])
@scope.project.tags = tags
deleteTag: (tag) ->
tags = _.clone(@scope.project.tags)
_.pull(tags, tag[0])
_.remove @scope.projectTags, (it) => it[0] == tag[0]
@scope.project.tags = tags
module.controller("ProjectProfileController", ProjectProfileController) module.controller("ProjectProfileController", ProjectProfileController)
@ -222,10 +244,12 @@ ProjectModulesDirective = ($repo, $confirm, $loading, projectService) ->
$el.on "change", ".module-activation.module-direct-active input", (event) -> $el.on "change", ".module-activation.module-direct-active input", (event) ->
event.preventDefault() event.preventDefault()
submit()
$scope.$applyAsync(submit)
$el.on "submit", "form", (event) -> $el.on "submit", "form", (event) ->
event.preventDefault() event.preventDefault()
submit() submit()
$el.on "click", ".save", (event) -> $el.on "click", ".save", (event) ->
@ -401,6 +425,10 @@ class CsvExporterController extends taiga.Controller
@._generateUuid() @._generateUuid()
class CsvExporterEpicsController extends CsvExporterController
type: "epics"
class CsvExporterUserstoriesController extends CsvExporterController class CsvExporterUserstoriesController extends CsvExporterController
type: "userstories" type: "userstories"
@ -413,6 +441,7 @@ class CsvExporterIssuesController extends CsvExporterController
type: "issues" type: "issues"
module.controller("CsvExporterEpicsController", CsvExporterEpicsController)
module.controller("CsvExporterUserstoriesController", CsvExporterUserstoriesController) module.controller("CsvExporterUserstoriesController", CsvExporterUserstoriesController)
module.controller("CsvExporterTasksController", CsvExporterTasksController) module.controller("CsvExporterTasksController", CsvExporterTasksController)
module.controller("CsvExporterIssuesController", CsvExporterIssuesController) module.controller("CsvExporterIssuesController", CsvExporterIssuesController)
@ -422,6 +451,21 @@ module.controller("CsvExporterIssuesController", CsvExporterIssuesController)
## CSV Directive ## CSV Directive
############################################################################# #############################################################################
CsvEpicDirective = ($translate) ->
link = ($scope) ->
$scope.sectionTitle = "ADMIN.CSV.SECTION_TITLE_EPIC"
return {
controller: "CsvExporterEpicsController",
controllerAs: "ctrl",
templateUrl: "admin/project-csv.html",
link: link,
scope: true
}
module.directive("tgCsvEpic", ["$translate", CsvEpicDirective])
CsvUsDirective = ($translate) -> CsvUsDirective = ($translate) ->
link = ($scope) -> link = ($scope) ->
$scope.sectionTitle = "ADMIN.CSV.SECTION_TITLE_US" $scope.sectionTitle = "ADMIN.CSV.SECTION_TITLE_US"

View File

@ -31,6 +31,8 @@ joinStr = @.taiga.joinStr
groupBy = @.taiga.groupBy groupBy = @.taiga.groupBy
bindOnce = @.taiga.bindOnce bindOnce = @.taiga.bindOnce
debounce = @.taiga.debounce debounce = @.taiga.debounce
getDefaulColorList = @.taiga.getDefaulColorList
module = angular.module("taigaAdmin") module = angular.module("taigaAdmin")
@ -50,11 +52,12 @@ class ProjectValuesSectionController extends mixOf(taiga.Controller, taiga.PageM
"$tgLocation", "$tgLocation",
"$tgNavUrls", "$tgNavUrls",
"tgAppMetaService", "tgAppMetaService",
"$translate" "$translate",
"tgErrorHandlingService"
] ]
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, @navUrls, constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, @navUrls,
@appMetaService, @translate) -> @appMetaService, @translate, @errorHandlingService) ->
@scope.project = {} @scope.project = {}
promise = @.loadInitialData() promise = @.loadInitialData()
@ -74,7 +77,7 @@ class ProjectValuesSectionController extends mixOf(taiga.Controller, taiga.PageM
loadProject: -> loadProject: ->
return @rs.projects.getBySlug(@params.pslug).then (project) => return @rs.projects.getBySlug(@params.pslug).then (project) =>
if not project.i_am_admin if not project.i_am_admin
@location.path(@navUrls.resolve("permission-denied")) @errorHandlingService.permissionDenied()
@scope.projectId = project.id @scope.projectId = project.id
@scope.project = project @scope.project = project
@ -156,7 +159,7 @@ ProjectValuesDirective = ($log, $repo, $confirm, $location, animationFrame, $tra
pixels: 30, pixels: 30,
scrollWhenOutside: true, scrollWhenOutside: true,
autoScroll: () -> autoScroll: () ->
return this.down && drake.dragging; return this.down && drake.dragging
}) })
$scope.$on "$destroy", -> $scope.$on "$destroy", ->
@ -178,7 +181,9 @@ ProjectValuesDirective = ($log, $repo, $confirm, $location, animationFrame, $tra
} }
initializeTextTranslations = -> initializeTextTranslations = ->
$scope.addNewElementText = $translate.instant("ADMIN.PROJECT_VALUES_#{objName.toUpperCase()}.ACTION_ADD") $scope.addNewElementText = $translate.instant(
"ADMIN.PROJECT_VALUES_#{objName.toUpperCase()}.ACTION_ADD"
)
initializeNewValue() initializeNewValue()
initializeTextTranslations() initializeTextTranslations()
@ -265,14 +270,6 @@ ProjectValuesDirective = ($log, $repo, $confirm, $location, animationFrame, $tra
editionRow.removeClass('hidden') editionRow.removeClass('hidden')
editionRow.find('input:visible').first().focus().select() editionRow.find('input:visible').first().focus().select()
$el.on "keyup", ".edition input", (event) ->
if event.keyCode == 13
target = angular.element(event.currentTarget)
saveValue(target)
else if event.keyCode == 27
target = angular.element(event.currentTarget)
cancel(target)
$el.on "keyup", ".new-value input", (event) -> $el.on "keyup", ".new-value input", (event) ->
if event.keyCode == 13 if event.keyCode == 13
target = $el.find(".new-value") target = $el.find(".new-value")
@ -327,7 +324,8 @@ ProjectValuesDirective = ($log, $repo, $confirm, $location, animationFrame, $tra
return {link:link} return {link:link}
module.directive("tgProjectValues", ["$log", "$tgRepo", "$tgConfirm", "$tgLocation", "animationFrame", "$translate", "$rootScope", ProjectValuesDirective]) module.directive("tgProjectValues", ["$log", "$tgRepo", "$tgConfirm", "$tgLocation", "animationFrame",
"$translate", "$rootScope", ProjectValuesDirective])
############################################################################# #############################################################################
@ -338,6 +336,12 @@ ColorSelectionDirective = () ->
## Color selection Link ## Color selection Link
link = ($scope, $el, $attrs, $model) -> link = ($scope, $el, $attrs, $model) ->
$scope.colorList = getDefaulColorList()
$scope.allowEmpty = false
if $attrs.tgAllowEmpty
$scope.allowEmpty = true
$ctrl = $el.controller() $ctrl = $el.controller()
$scope.$watch $attrs.ngModel, (element) -> $scope.$watch $attrs.ngModel, (element) ->
@ -348,7 +352,7 @@ ColorSelectionDirective = () ->
event.preventDefault() event.preventDefault()
event.stopPropagation() event.stopPropagation()
target = angular.element(event.currentTarget) target = angular.element(event.currentTarget)
$el.find(".select-color").hide() $(".select-color").hide()
target.siblings(".select-color").show() target.siblings(".select-color").show()
# Hide when click outside # Hide when click outside
body = angular.element("body") body = angular.element("body")
@ -371,6 +375,16 @@ ColorSelectionDirective = () ->
$model.$modelValue.color = $scope.color $model.$modelValue.color = $scope.color
$el.find(".select-color").hide() $el.find(".select-color").hide()
$el.on "keyup", "input", (event) ->
event.stopPropagation()
if event.keyCode == 13
$scope.$apply ->
$model.$modelValue.color = $scope.color
$el.find(".select-color").hide()
else if event.keyCode == 27
$el.find(".select-color").hide()
$scope.$on "$destroy", -> $scope.$on "$destroy", ->
$el.off() $el.off()
@ -688,3 +702,289 @@ ProjectCustomAttributesDirective = ($log, $confirm, animationFrame, $translate)
module.directive("tgProjectCustomAttributes", ["$log", "$tgConfirm", "animationFrame", "$translate", module.directive("tgProjectCustomAttributes", ["$log", "$tgConfirm", "animationFrame", "$translate",
ProjectCustomAttributesDirective]) ProjectCustomAttributesDirective])
#############################################################################
## Tags Controller
#############################################################################
class ProjectTagsController extends taiga.Controller
@.$inject = [
"$scope",
"$rootScope",
"$tgRepo",
"$tgConfirm",
"$tgResources",
"$tgModel",
]
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @model) ->
@.loading = true
@rootscope.$on("project:loaded", @.loadTags)
loadTags: =>
return @rs.projects.tagsColors(@scope.projectId).then (tags) =>
@scope.projectTagsAll = _.map tags.getAttrs(), (color, name) =>
@model.make_model('tag', {name: name, color: color})
@.filterAndSortTags()
@.loading = false
filterAndSortTags: =>
@scope.projectTags = _.filter(
_.sortBy(@scope.projectTagsAll, "name"),
(tag) => tag.name.indexOf(@scope.tagsFilter.name) != -1
)
createTag: (tag, color) =>
return @rs.projects.createTag(@scope.projectId, tag, color)
editTag: (from_tag, to_tag, color) =>
if from_tag == to_tag
to_tag = null
return @rs.projects.editTag(@scope.projectId, from_tag, to_tag, color)
deleteTag: (tag) =>
@scope.loadingDelete = true
return @rs.projects.deleteTag(@scope.projectId, tag).finally =>
@scope.loadingDelete = false
startMixingTags: (tag) =>
@scope.mixingTags.toTag = tag.name
toggleMixingFromTags: (tag) =>
if tag.name != @scope.mixingTags.toTag
index = @scope.mixingTags.fromTags.indexOf(tag.name)
if index == -1
@scope.mixingTags.fromTags.push(tag.name)
else
@scope.mixingTags.fromTags.splice(index, 1)
confirmMixingTags: () =>
toTag = @scope.mixingTags.toTag
fromTags = @scope.mixingTags.fromTags
@scope.loadingMixing = true
@rs.projects.mixTags(@scope.projectId, toTag, fromTags)
.then =>
@.cancelMixingTags()
@.loadTags()
.finally =>
@scope.loadingMixing = false
cancelMixingTags: () =>
@scope.mixingTags.toTag = null
@scope.mixingTags.fromTags = []
mixingClass: (tag) =>
if @scope.mixingTags.toTag != null
if tag.name == @scope.mixingTags.toTag
return "mixing-tags-to"
else if @scope.mixingTags.fromTags.indexOf(tag.name) != -1
return "mixing-tags-from"
module.controller("ProjectTagsController", ProjectTagsController)
#############################################################################
## Tags directive
#############################################################################
ProjectTagsDirective = ($log, $repo, $confirm, $location, animationFrame, $translate, $rootscope) ->
link = ($scope, $el, $attrs) ->
$window = $(window)
$ctrl = $el.controller()
valueType = $attrs.type
objName = $attrs.objname
initializeNewValue = ->
$scope.newValue = {
"tag": ""
"color": ""
}
initializeTagsFilter = ->
$scope.tagsFilter = {
"name": ""
}
initializeMixingTags = ->
$scope.mixingTags = {
"toTag": null,
"fromTags": []
}
initializeTextTranslations = ->
$scope.addNewElementText = $translate.instant("ADMIN.PROJECT_VALUES_TAGS.ACTION_ADD")
initializeNewValue()
initializeTagsFilter()
initializeMixingTags()
initializeTextTranslations()
$rootscope.$on "$translateChangeEnd", ->
$scope.$evalAsync(initializeTextTranslations)
goToBottomList = (focus = false) =>
table = $el.find(".table-main")
$(document.body).scrollTop(table.offset().top + table.height())
if focus
$el.find(".new-value input:visible").first().focus()
saveValue = (target) =>
formEl = target.parents("form")
form = formEl.checksley()
return if not form.validate()
tag = formEl.scope().tag
originalTag = tag.clone()
originalTag.revert()
$scope.loadingEdit = true
promise = $ctrl.editTag(originalTag.name, tag.name, tag.color)
promise.then =>
$ctrl.loadTags().then =>
row = target.parents(".row.table-main")
row.addClass("hidden")
$scope.loadingEdit = false
row.siblings(".visualization").removeClass('hidden')
promise.then null, (response) ->
$scope.loadingEdit = false
form.setErrors(response.data)
saveNewValue = (target) =>
formEl = target.parents("form")
formEl = target
form = formEl.checksley()
return if not form.validate()
$scope.loadingCreate = true
promise = $ctrl.createTag($scope.newValue.tag, $scope.newValue.color)
promise.then (data) =>
$ctrl.loadTags().then =>
$scope.loadingCreate = false
target.addClass("hidden")
initializeNewValue()
promise.then null, (response) ->
$scope.loadingCreate = false
form.setErrors(response.data)
cancel = (target) ->
row = target.parents(".row.table-main")
formEl = target.parents("form")
tag = formEl.scope().tag
$scope.$apply ->
row.addClass("hidden")
tag.revert()
row.siblings(".visualization").removeClass('hidden')
$scope.$watch "tagsFilter.name", (tagsFilter) ->
$ctrl.filterAndSortTags()
$window.on "keyup", (event) ->
if event.keyCode == 27
$scope.$apply ->
initializeMixingTags()
$el.on "click", ".show-add-new", (event) ->
event.preventDefault()
$el.find(".new-value").removeClass('hidden')
$el.on "click", ".add-new", debounce 2000, (event) ->
event.preventDefault()
target = $el.find(".new-value")
saveNewValue(target)
$el.on "click", ".delete-new", (event) ->
event.preventDefault()
$el.find(".new-value").addClass("hidden")
initializeNewValue()
$el.on "click", ".mix-tags", (event) ->
event.preventDefault()
target = angular.element(event.currentTarget)
$scope.$apply ->
$ctrl.startMixingTags(target.parents('form').scope().tag)
$el.on "click", ".mixing-row", (event) ->
event.preventDefault()
target = angular.element(event.currentTarget)
$scope.$apply ->
$ctrl.toggleMixingFromTags(target.parents('form').scope().tag)
$el.on "click", ".mixing-confirm", (event) ->
event.preventDefault()
event.stopPropagation()
$scope.$apply ->
$ctrl.confirmMixingTags()
$el.on "click", ".mixing-cancel", (event) ->
event.preventDefault()
event.stopPropagation()
$scope.$apply ->
$ctrl.cancelMixingTags()
$el.on "click", ".edit-value", (event) ->
event.preventDefault()
target = angular.element(event.currentTarget)
row = target.parents(".row.table-main")
row.addClass("hidden")
editionRow = row.siblings(".edition")
editionRow.removeClass('hidden')
editionRow.find('input:visible').first().focus().select()
$el.on "keyup", ".new-value input", (event) ->
if event.keyCode == 13
target = $el.find(".new-value")
saveNewValue(target)
else if event.keyCode == 27
$el.find(".new-value").addClass("hidden")
initializeNewValue()
$el.on "keyup", ".status-name input", (event) ->
target = angular.element(event.currentTarget)
if event.keyCode == 13
saveValue(target)
else if event.keyCode == 27
cancel(target)
$el.on "click", ".save", (event) ->
event.preventDefault()
target = angular.element(event.currentTarget)
saveValue(target)
$el.on "click", ".cancel", (event) ->
event.preventDefault()
target = angular.element(event.currentTarget)
cancel(target)
$el.on "click", ".delete-tag", (event) ->
event.preventDefault()
target = angular.element(event.currentTarget)
formEl = target.parents("form")
tag = formEl.scope().tag
title = $translate.instant("ADMIN.COMMON.TITLE_ACTION_DELETE_TAG")
$confirm.askOnDelete(title, tag.name).then (response) ->
onSucces = ->
$ctrl.loadTags().finally ->
response.finish()
onError = ->
$confirm.notify("error")
$ctrl.deleteTag(tag.name).then(onSucces, onError)
$scope.$on "$destroy", ->
$el.off()
$window.off()
return {link:link}
module.directive("tgProjectTags", ["$log", "$tgRepo", "$tgConfirm", "$tgLocation", "animationFrame",
"$translate", "$rootScope", ProjectTagsDirective])

View File

@ -48,11 +48,12 @@ class RolesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fil
"$tgLocation", "$tgLocation",
"$tgNavUrls", "$tgNavUrls",
"tgAppMetaService", "tgAppMetaService",
"$translate" "$translate",
"tgErrorHandlingService"
] ]
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, @navUrls, constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, @navUrls,
@appMetaService, @translate) -> @appMetaService, @translate, @errorHandlingService) ->
bindMethods(@) bindMethods(@)
@scope.sectionName = "ADMIN.MENU.PERMISSIONS" @scope.sectionName = "ADMIN.MENU.PERMISSIONS"
@ -71,7 +72,7 @@ class RolesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fil
loadProject: -> loadProject: ->
return @rs.projects.getBySlug(@params.pslug).then (project) => return @rs.projects.getBySlug(@params.pslug).then (project) =>
if not project.i_am_admin if not project.i_am_admin
@location.path(@navUrls.resolve("permission-denied")) @errorHandlingService.permissionDenied()
@scope.projectId = project.id @scope.projectId = project.id
@scope.project = project @scope.project = project
@ -98,6 +99,7 @@ class RolesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fil
@scope.roles = roles @scope.roles = roles
@scope.role = @scope.roles[0] @scope.role = @scope.roles[0]
return roles return roles
loadInitialData: -> loadInitialData: ->
@ -351,6 +353,18 @@ RolePermissionsDirective = ($rootscope, $repo, $confirm, $compile) ->
categories = [] categories = []
epicPermissions = [
{ key: "view_epics", name: "COMMON.PERMISIONS_CATEGORIES.EPICS.VIEW_EPICS"}
{ key: "add_epic", name: "COMMON.PERMISIONS_CATEGORIES.EPICS.ADD_EPICS"}
{ key: "modify_epic", name: "COMMON.PERMISIONS_CATEGORIES.EPICS.MODIFY_EPICS"}
{ key: "comment_epic", name: "COMMON.PERMISIONS_CATEGORIES.EPICS.COMMENT_EPICS"}
{ key: "delete_epic", name: "COMMON.PERMISIONS_CATEGORIES.EPICS.DELETE_EPICS"}
]
categories.push({
name: "COMMON.PERMISIONS_CATEGORIES.EPICS.NAME" ,
permissions: setActivePermissions(epicPermissions)
})
milestonePermissions = [ milestonePermissions = [
{ key: "view_milestones", name: "COMMON.PERMISIONS_CATEGORIES.SPRINTS.VIEW_SPRINTS"} { key: "view_milestones", name: "COMMON.PERMISIONS_CATEGORIES.SPRINTS.VIEW_SPRINTS"}
{ key: "add_milestone", name: "COMMON.PERMISIONS_CATEGORIES.SPRINTS.ADD_SPRINTS"} { key: "add_milestone", name: "COMMON.PERMISIONS_CATEGORIES.SPRINTS.ADD_SPRINTS"}
@ -366,6 +380,7 @@ RolePermissionsDirective = ($rootscope, $repo, $confirm, $compile) ->
{ key: "view_us", name: "COMMON.PERMISIONS_CATEGORIES.USER_STORIES.VIEW_USER_STORIES"} { key: "view_us", name: "COMMON.PERMISIONS_CATEGORIES.USER_STORIES.VIEW_USER_STORIES"}
{ key: "add_us", name: "COMMON.PERMISIONS_CATEGORIES.USER_STORIES.ADD_USER_STORIES"} { key: "add_us", name: "COMMON.PERMISIONS_CATEGORIES.USER_STORIES.ADD_USER_STORIES"}
{ key: "modify_us", name: "COMMON.PERMISIONS_CATEGORIES.USER_STORIES.MODIFY_USER_STORIES"} { key: "modify_us", name: "COMMON.PERMISIONS_CATEGORIES.USER_STORIES.MODIFY_USER_STORIES"}
{ key: "comment_us", name: "COMMON.PERMISIONS_CATEGORIES.USER_STORIES.COMMENT_USER_STORIES"}
{ key: "delete_us", name: "COMMON.PERMISIONS_CATEGORIES.USER_STORIES.DELETE_USER_STORIES"} { key: "delete_us", name: "COMMON.PERMISIONS_CATEGORIES.USER_STORIES.DELETE_USER_STORIES"}
] ]
categories.push({ categories.push({
@ -377,6 +392,7 @@ RolePermissionsDirective = ($rootscope, $repo, $confirm, $compile) ->
{ key: "view_tasks", name: "COMMON.PERMISIONS_CATEGORIES.TASKS.VIEW_TASKS"} { key: "view_tasks", name: "COMMON.PERMISIONS_CATEGORIES.TASKS.VIEW_TASKS"}
{ key: "add_task", name: "COMMON.PERMISIONS_CATEGORIES.TASKS.ADD_TASKS"} { key: "add_task", name: "COMMON.PERMISIONS_CATEGORIES.TASKS.ADD_TASKS"}
{ key: "modify_task", name: "COMMON.PERMISIONS_CATEGORIES.TASKS.MODIFY_TASKS"} { key: "modify_task", name: "COMMON.PERMISIONS_CATEGORIES.TASKS.MODIFY_TASKS"}
{ key: "comment_task", name: "COMMON.PERMISIONS_CATEGORIES.USER_STORIES.COMMENT_TASKS"}
{ key: "delete_task", name: "COMMON.PERMISIONS_CATEGORIES.TASKS.DELETE_TASKS"} { key: "delete_task", name: "COMMON.PERMISIONS_CATEGORIES.TASKS.DELETE_TASKS"}
] ]
categories.push({ categories.push({
@ -388,6 +404,7 @@ RolePermissionsDirective = ($rootscope, $repo, $confirm, $compile) ->
{ key: "view_issues", name: "COMMON.PERMISIONS_CATEGORIES.ISSUES.VIEW_ISSUES"} { key: "view_issues", name: "COMMON.PERMISIONS_CATEGORIES.ISSUES.VIEW_ISSUES"}
{ key: "add_issue", name: "COMMON.PERMISIONS_CATEGORIES.ISSUES.ADD_ISSUES"} { key: "add_issue", name: "COMMON.PERMISIONS_CATEGORIES.ISSUES.ADD_ISSUES"}
{ key: "modify_issue", name: "COMMON.PERMISIONS_CATEGORIES.ISSUES.MODIFY_ISSUES"} { key: "modify_issue", name: "COMMON.PERMISIONS_CATEGORIES.ISSUES.MODIFY_ISSUES"}
{ key: "comment_issue", name: "COMMON.PERMISIONS_CATEGORIES.USER_STORIES.COMMENT_ISSUES"}
{ key: "delete_issue", name: "COMMON.PERMISIONS_CATEGORIES.ISSUES.DELETE_ISSUES"} { key: "delete_issue", name: "COMMON.PERMISIONS_CATEGORIES.ISSUES.DELETE_ISSUES"}
] ]
categories.push({ categories.push({

View File

@ -45,10 +45,11 @@ class WebhooksController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.
"$tgLocation", "$tgLocation",
"$tgNavUrls", "$tgNavUrls",
"tgAppMetaService", "tgAppMetaService",
"$translate" "$translate",
"tgErrorHandlingService"
] ]
constructor: (@scope, @repo, @rs, @params, @location, @navUrls, @appMetaService, @translate) -> constructor: (@scope, @repo, @rs, @params, @location, @navUrls, @appMetaService, @translate, @errorHandlingService) ->
bindMethods(@) bindMethods(@)
@scope.sectionName = "ADMIN.WEBHOOKS.SECTION_NAME" @scope.sectionName = "ADMIN.WEBHOOKS.SECTION_NAME"
@ -72,7 +73,7 @@ class WebhooksController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.
loadProject: -> loadProject: ->
return @rs.projects.getBySlug(@params.pslug).then (project) => return @rs.projects.getBySlug(@params.pslug).then (project) =>
if not project.i_am_admin if not project.i_am_admin
@location.path(@navUrls.resolve("permission-denied")) @errorHandlingService.permissionDenied()
@scope.projectId = project.id @scope.projectId = project.id
@scope.project = project @scope.project = project
@ -193,15 +194,22 @@ WebhookDirective = ($rs, $repo, $confirm, $loading, $translate) ->
$el.on "click", ".toggle-history", (event) -> $el.on "click", ".toggle-history", (event) ->
target = angular.element(event.currentTarget) target = angular.element(event.currentTarget)
if not webhook.logs? or webhook.logs.length == 0 if not webhook.logs? or webhook.logs.length == 0
updateLogs().then -> updateLogs().then ->
#Waiting for ng-repeat to finish #Waiting for ng-repeat to finish
timeout 0, -> timeout 0, ->
$el.find(".webhooks-history").toggleClass("open") $el.find(".webhooks-history")
.toggleClass("open")
.slideToggle()
updateShowHideHistoryText() updateShowHideHistoryText()
else else
$el.find(".webhooks-history").toggleClass("open") $el.find(".webhooks-history")
.toggleClass("open")
.slideToggle()
$scope.$apply () -> $scope.$apply () ->
updateShowHideHistoryText() updateShowHideHistoryText()
@ -578,3 +586,50 @@ ValidOriginIpsDirective = ->
} }
module.directive("tgValidOriginIps", ValidOriginIpsDirective) module.directive("tgValidOriginIps", ValidOriginIpsDirective)
#############################################################################
## Gogs Controller
#############################################################################
class GogsController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.FiltersMixin)
@.$inject = [
"$scope",
"$tgRepo",
"$tgResources",
"$routeParams",
"tgAppMetaService",
"$translate"
]
constructor: (@scope, @repo, @rs, @params, @appMetaService, @translate) ->
bindMethods(@)
@scope.sectionName = @translate.instant("ADMIN.GOGS.SECTION_NAME")
@scope.project = {}
promise = @.loadInitialData()
promise.then () =>
title = @translate.instant("ADMIN.GOGS.PAGE_TITLE", {projectName: @scope.project.name})
description = @scope.project.description
@appMetaService.setAll(title, description)
promise.then null, @.onInitialDataError.bind(@)
loadModules: ->
return @rs.modules.list(@scope.projectId, "gogs").then (gogs) =>
@scope.gogs = gogs
loadProject: ->
return @rs.projects.getBySlug(@params.pslug).then (project) =>
@scope.projectId = project.id
@scope.project = project
@scope.$emit('project:loaded', project)
return project
loadInitialData: ->
promise = @.loadProject()
promise.then(=> @.loadModules())
return promise
module.controller("GogsController", GogsController)

View File

@ -37,12 +37,13 @@ class LoginPage
constructor: (currentUserService, $location, $navUrls, $routeParams) -> constructor: (currentUserService, $location, $navUrls, $routeParams) ->
if currentUserService.isAuthenticated() if currentUserService.isAuthenticated()
url = $navUrls.resolve("home") if not $routeParams['force_login']
if $routeParams['next'] url = $navUrls.resolve("home")
url = $routeParams['next'] if $routeParams['next']
$location.search('next', null) url = decodeURIComponent($routeParams['next'])
$location.search('next', null)
$location.path(url) $location.url(url)
module.controller('LoginPage', LoginPage) module.controller('LoginPage', LoginPage)
@ -243,8 +244,9 @@ PublicRegisterMessageDirective = ($config, $navUrls, $routeParams, templates) ->
return "" return ""
url = $navUrls.resolve("register") url = $navUrls.resolve("register")
if $routeParams['next'] and $routeParams['next'] != $navUrls.resolve("register")
nextUrl = encodeURIComponent($routeParams['next']) if $routeParams['force_next']
nextUrl = encodeURIComponent($routeParams['force_next'])
url += "?next=#{nextUrl}" url += "?next=#{nextUrl}"
return template({url:url}) return template({url:url})
@ -259,7 +261,7 @@ module.directive("tgPublicRegisterMessage", ["$tgConfig", "$tgNavUrls", "$routeP
"$tgTemplate", PublicRegisterMessageDirective]) "$tgTemplate", PublicRegisterMessageDirective])
LoginDirective = ($auth, $confirm, $location, $config, $routeParams, $navUrls, $events, $translate) -> LoginDirective = ($auth, $confirm, $location, $config, $routeParams, $navUrls, $events, $translate, $window) ->
link = ($scope, $el, $attrs) -> link = ($scope, $el, $attrs) ->
form = new checksley.Form($el.find("form.login-form")) form = new checksley.Form($el.find("form.login-form"))
@ -268,9 +270,16 @@ LoginDirective = ($auth, $confirm, $location, $config, $routeParams, $navUrls, $
else else
$scope.nextUrl = $navUrls.resolve("home") $scope.nextUrl = $navUrls.resolve("home")
if $routeParams['force_next']
$scope.nextUrl = decodeURIComponent($routeParams['force_next'])
onSuccess = (response) -> onSuccess = (response) ->
$events.setupConnection() $events.setupConnection()
$location.url($scope.nextUrl)
if $scope.nextUrl.indexOf('http') == 0
$window.location.href = $scope.nextUrl
else
$location.url($scope.nextUrl)
onError = (response) -> onError = (response) ->
$confirm.notify("light-error", $translate.instant("LOGIN_FORM.ERROR_AUTH_INCORRECT")) $confirm.notify("light-error", $translate.instant("LOGIN_FORM.ERROR_AUTH_INCORRECT"))
@ -308,14 +317,14 @@ LoginDirective = ($auth, $confirm, $location, $config, $routeParams, $navUrls, $
return {link:link} return {link:link}
module.directive("tgLogin", ["$tgAuth", "$tgConfirm", "$tgLocation", "$tgConfig", "$routeParams", module.directive("tgLogin", ["$tgAuth", "$tgConfirm", "$tgLocation", "$tgConfig", "$routeParams",
"$tgNavUrls", "$tgEvents", "$translate", LoginDirective]) "$tgNavUrls", "$tgEvents", "$translate", "$window", LoginDirective])
############################################################################# #############################################################################
## Register Directive ## Register Directive
############################################################################# #############################################################################
RegisterDirective = ($auth, $confirm, $location, $navUrls, $config, $routeParams, $analytics, $translate) -> RegisterDirective = ($auth, $confirm, $location, $navUrls, $config, $routeParams, $analytics, $translate, $window) ->
link = ($scope, $el, $attrs) -> link = ($scope, $el, $attrs) ->
if not $config.get("publicRegisterEnabled") if not $config.get("publicRegisterEnabled")
$location.path($navUrls.resolve("not-found")) $location.path($navUrls.resolve("not-found"))
@ -324,12 +333,18 @@ RegisterDirective = ($auth, $confirm, $location, $navUrls, $config, $routeParams
$scope.data = {} $scope.data = {}
form = $el.find("form").checksley({onlyOneErrorElement: true}) form = $el.find("form").checksley({onlyOneErrorElement: true})
$scope.nextUrl = $navUrls.resolve("home") if $routeParams['next'] and $routeParams['next'] != $navUrls.resolve("login")
$scope.nextUrl = decodeURIComponent($routeParams['next'])
else
$scope.nextUrl = $navUrls.resolve("home")
onSuccessSubmit = (response) -> onSuccessSubmit = (response) ->
$analytics.trackEvent("auth", "register", "user registration", 1) $analytics.trackEvent("auth", "register", "user registration", 1)
$location.url($scope.nextUrl) if $scope.nextUrl.indexOf('http') == 0
$window.location.href = $scope.nextUrl
else
$location.url($scope.nextUrl)
onErrorSubmit = (response) -> onErrorSubmit = (response) ->
if response.data._error_message if response.data._error_message
@ -357,7 +372,7 @@ RegisterDirective = ($auth, $confirm, $location, $navUrls, $config, $routeParams
return {link:link} return {link:link}
module.directive("tgRegister", ["$tgAuth", "$tgConfirm", "$tgLocation", "$tgNavUrls", "$tgConfig", module.directive("tgRegister", ["$tgAuth", "$tgConfirm", "$tgLocation", "$tgNavUrls", "$tgConfig",
"$routeParams", "$tgAnalytics", "$translate", RegisterDirective]) "$routeParams", "$tgAnalytics", "$translate", "$window", RegisterDirective])
############################################################################# #############################################################################
@ -458,13 +473,14 @@ module.directive("tgChangePasswordFromRecovery", ["$tgAuth", "$tgConfirm", "$tgL
## Invitation ## Invitation
############################################################################# #############################################################################
InvitationDirective = ($auth, $confirm, $location, $params, $navUrls, $analytics, $translate) -> InvitationDirective = ($auth, $confirm, $location, $params, $navUrls, $analytics, $translate, config) ->
link = ($scope, $el, $attrs) -> link = ($scope, $el, $attrs) ->
token = $params.token token = $params.token
promise = $auth.getInvitation(token) promise = $auth.getInvitation(token)
promise.then (invitation) -> promise.then (invitation) ->
$scope.invitation = invitation $scope.invitation = invitation
$scope.publicRegisterEnabled = config.get("publicRegisterEnabled")
promise.then null, (response) -> promise.then null, (response) ->
$location.path($navUrls.resolve("login")) $location.path($navUrls.resolve("login"))
@ -535,7 +551,7 @@ InvitationDirective = ($auth, $confirm, $location, $params, $navUrls, $analytics
return {link:link} return {link:link}
module.directive("tgInvitation", ["$tgAuth", "$tgConfirm", "$tgLocation", "$routeParams", module.directive("tgInvitation", ["$tgAuth", "$tgConfirm", "$tgLocation", "$routeParams",
"$tgNavUrls", "$tgAnalytics", "$translate", InvitationDirective]) "$tgNavUrls", "$tgAnalytics", "$translate", "$tgConfig", InvitationDirective])
############################################################################# #############################################################################

View File

@ -1,185 +0,0 @@
###
# Copyright (C) 2014-2016 Andrey Antukh <niwi@niwi.nz>
# Copyright (C) 2014-2016 Jesús Espino Garcia <jespinog@gmail.com>
# Copyright (C) 2014-2016 David Barragán Merino <bameda@dbarragan.com>
# Copyright (C) 2014-2016 Alejandro Alonso <alejandro.alonso@kaleidos.net>
# Copyright (C) 2014-2016 Juan Francisco Alcántara <juanfran.alcantara@kaleidos.net>
# Copyright (C) 2014-2016 Xavi Julian <xavier.julian@kaleidos.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# File: modules/backlog/main.coffee
###
taiga = @.taiga
mixOf = @.taiga.mixOf
toggleText = @.taiga.toggleText
scopeDefer = @.taiga.scopeDefer
bindOnce = @.taiga.bindOnce
groupBy = @.taiga.groupBy
debounceLeading = @.taiga.debounceLeading
module = angular.module("taigaBacklog")
#############################################################################
## Issues Filters Directive
#############################################################################
BacklogFiltersDirective = ($q, $log, $location, $template, $compile) ->
template = $template.get("backlog/filters.html", true)
templateSelected = $template.get("backlog/filter-selected.html", true)
link = ($scope, $el, $attrs) ->
currentFiltersType = ''
$ctrl = $el.closest(".wrapper").controller()
selectedFilters = []
showFilters = (title, type) ->
$el.find(".filters-cats").hide()
$el.find(".filter-list").removeClass("hidden")
$el.find("h2.breadcrumb").removeClass("hidden")
$el.find("h2 a.subfilter span.title").html(title)
$el.find("h2 a.subfilter span.title").prop("data-type", type)
currentFiltersType = getFiltersType()
showCategories = ->
$el.find(".filters-cats").show()
$el.find(".filter-list").addClass("hidden")
$el.find("h2.breadcrumb").addClass("hidden")
initializeSelectedFilters = () ->
showCategories()
selectedFilters = []
for name, values of $scope.filters
for val in values
selectedFilters.push(val) if val.selected
renderSelectedFilters()
renderSelectedFilters = ->
_.map selectedFilters, (f) =>
if f.color
f.style = "border-left: 3px solid #{f.color}"
html = templateSelected({filters: selectedFilters})
html = $compile(html)($scope)
$el.find(".filters-applied").html(html)
renderFilters = (filters) ->
_.map filters, (f) =>
if f.color
f.style = "border-left: 3px solid #{f.color}"
html = template({filters:filters})
html = $compile(html)($scope)
$el.find(".filter-list").html(html)
getFiltersType = () ->
return $el.find("h2 a.subfilter span.title").prop('data-type')
reloadUserstories = () ->
currentFiltersType = getFiltersType()
$q.all([$ctrl.loadUserstories(true), $ctrl.generateFilters()]).then () ->
currentFilters = $scope.filters[currentFiltersType]
renderFilters(_.reject(currentFilters, "selected"))
toggleFilterSelection = (type, id) ->
currentFiltersType = getFiltersType()
filters = $scope.filters[type]
filter = _.find(filters, {id: id})
filter.selected = (not filter.selected)
if filter.selected
selectedFilters.push(filter)
$scope.$apply ->
$ctrl.selectFilter(type, id)
else
selectedFilters = _.reject selectedFilters, (selected) ->
return filter.type == selected.type && filter.id == selected.id
$ctrl.unselectFilter(type, id)
renderSelectedFilters(selectedFilters)
if type == currentFiltersType
renderFilters(_.reject(filters, "selected"))
reloadUserstories()
selectQFilter = debounceLeading 100, (value) ->
return if value is undefined
if value.length == 0
$ctrl.replaceFilter("q", null)
else
$ctrl.replaceFilter("q", value)
reloadUserstories()
$scope.$watch("filtersQ", selectQFilter)
## Angular Watchers
$scope.$on "backlog:loaded", (ctx) ->
initializeSelectedFilters()
$scope.$on "filters:update", (ctx) ->
$ctrl.generateFilters().then () ->
filters = $scope.filters[currentFiltersType]
if currentFiltersType
renderFilters(_.reject(filters, "selected"))
## Dom Event Handlers
$el.on "click", ".filters-cats > ul > li > a", (event) ->
event.preventDefault()
target = angular.element(event.currentTarget)
tags = $scope.filters[target.data("type")]
renderFilters(_.reject(tags, "selected"))
showFilters(target.attr("title"), target.data('type'))
$el.on "click", ".filters-inner > .filters-step-cat > .breadcrumb > .back", (event) ->
event.preventDefault()
showCategories()
$el.on "click", ".remove-filter", (event) ->
event.preventDefault()
target = angular.element(event.currentTarget).parent()
id = target.data("id")
type = target.data("type")
toggleFilterSelection(type, id)
$el.on "click", ".filter-list .single-filter", (event) ->
event.preventDefault()
target = angular.element(event.currentTarget)
if target.hasClass("active")
target.removeClass("active")
else
target.addClass("active")
id = target.data("id")
type = target.data("type")
toggleFilterSelection(type, id)
return {link:link}
module.directive("tgBacklogFilters", ["$q", "$log", "$tgLocation", "$tgTemplate", "$compile", BacklogFiltersDirective])

View File

@ -39,7 +39,7 @@ module = angular.module("taigaBacklog")
## Backlog Controller ## Backlog Controller
############################################################################# #############################################################################
class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.FiltersMixin) class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.FiltersMixin, taiga.UsFiltersMixin)
@.$inject = [ @.$inject = [
"$scope", "$scope",
"$rootScope", "$rootScope",
@ -56,18 +56,32 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
"$translate", "$translate",
"$tgLoading", "$tgLoading",
"tgResources", "tgResources",
"$tgQueueModelTransformation" "$tgQueueModelTransformation",
"tgErrorHandlingService",
"$tgStorage",
"tgFilterRemoteStorageService"
] ]
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, storeCustomFiltersName: 'backlog-custom-filters'
@location, @appMetaService, @navUrls, @events, @analytics, @translate, @loading, @rs2, @modelTransform) -> storeFiltersName: 'backlog-filters'
backlogOrder: {}
milestonesOrder: {}
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, @appMetaService, @navUrls,
@events, @analytics, @translate, @loading, @rs2, @modelTransform, @errorHandlingService,
@storage, @filterRemoteStorageService) ->
bindMethods(@) bindMethods(@)
@.backlogOrder = {}
@.milestonesOrder = {}
@.page = 1 @.page = 1
@.disablePagination = false @.disablePagination = false
@.firstLoadComplete = false @.firstLoadComplete = false
@scope.userstories = [] @scope.userstories = []
return if @.applyStoredFilters(@params.pslug, "backlog-filters")
@scope.sectionName = @translate.instant("BACKLOG.SECTION_NAME") @scope.sectionName = @translate.instant("BACKLOG.SECTION_NAME")
@showTags = false @showTags = false
@activeFilters = false @activeFilters = false
@ -96,15 +110,20 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
# On Error # On Error
promise.then null, @.onInitialDataError.bind(@) promise.then null, @.onInitialDataError.bind(@)
filtersReloadContent: () ->
@.loadUserstories(true)
initializeEventHandlers: -> initializeEventHandlers: ->
@scope.$on "usform:bulk:success", => @scope.$on "usform:bulk:success", =>
@.loadUserstories(true) @.loadUserstories(true)
@.loadProjectStats() @.loadProjectStats()
@confirm.notify("success")
@analytics.trackEvent("userstory", "create", "bulk create userstory on backlog", 1) @analytics.trackEvent("userstory", "create", "bulk create userstory on backlog", 1)
@scope.$on "sprintform:create:success", => @scope.$on "sprintform:create:success", =>
@.loadSprints() @.loadSprints()
@.loadProjectStats() @.loadProjectStats()
@confirm.notify("success")
@analytics.trackEvent("sprint", "create", "create sprint on backlog", 1) @analytics.trackEvent("sprint", "create", "create sprint on backlog", 1)
@scope.$on "usform:new:success", => @scope.$on "usform:new:success", =>
@ -112,6 +131,7 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
@.loadProjectStats() @.loadProjectStats()
@rootscope.$broadcast("filters:update") @rootscope.$broadcast("filters:update")
@confirm.notify("success")
@analytics.trackEvent("userstory", "create", "create userstory on backlog", 1) @analytics.trackEvent("userstory", "create", "create userstory on backlog", 1)
@scope.$on "sprintform:edit:success", => @scope.$on "sprintform:edit:success", =>
@ -174,6 +194,12 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
@scope.showGraphPlaceholder = !(stats.total_points? && stats.total_milestones?) @scope.showGraphPlaceholder = !(stats.total_points? && stats.total_milestones?)
return stats return stats
setMilestonesOrder: (sprints) ->
for sprint in sprints
@.milestonesOrder[sprint.id] = {}
for it in sprint.user_stories
@.milestonesOrder[sprint.id][it.id] = it.sprint_order
unloadClosedSprints: -> unloadClosedSprints: ->
@scope.$apply => @scope.$apply =>
@scope.closedSprints = [] @scope.closedSprints = []
@ -184,6 +210,8 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
return @rs.sprints.list(@scope.projectId, params).then (result) => return @rs.sprints.list(@scope.projectId, params).then (result) =>
sprints = result.milestones sprints = result.milestones
@.setMilestonesOrder(sprints)
@scope.totalClosedMilestones = result.closed @scope.totalClosedMilestones = result.closed
# NOTE: Fix order of USs because the filter orderBy does not work propertly in partials files # NOTE: Fix order of USs because the filter orderBy does not work propertly in partials files
@ -199,6 +227,8 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
return @rs.sprints.list(@scope.projectId, params).then (result) => return @rs.sprints.list(@scope.projectId, params).then (result) =>
sprints = result.milestones sprints = result.milestones
@.setMilestonesOrder(sprints)
@scope.totalMilestones = sprints @scope.totalMilestones = sprints
@scope.totalClosedMilestones = result.closed @scope.totalClosedMilestones = result.closed
@scope.totalOpenMilestones = result.open @scope.totalOpenMilestones = result.open
@ -220,47 +250,6 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
return sprints return sprints
restoreFilters: ->
selectedTags = @scope.oldSelectedTags
selectedStatuses = @scope.oldSelectedStatuses
return if !selectedStatuses and !selectedStatuses
@scope.filtersQ = @scope.filtersQOld
@.replaceFilter("q", @scope.filtersQ)
_.each [selectedTags, selectedStatuses], (filterGrp) =>
_.each filterGrp, (item) =>
filters = @scope.filters[item.type]
filter = _.find(filters, {id: item.id})
filter.selected = true
@.selectFilter(item.type, item.id)
@.loadUserstories()
resetFilters: ->
selectedTags = _.filter(@scope.filters.tags, "selected")
selectedStatuses = _.filter(@scope.filters.status, "selected")
@scope.oldSelectedTags = selectedTags
@scope.oldSelectedStatuses = selectedStatuses
@scope.filtersQOld = @scope.filtersQ
@scope.filtersQ = undefined
@.replaceFilter("q", @scope.filtersQ)
_.each [selectedTags, selectedStatuses], (filterGrp) =>
_.each filterGrp, (item) =>
filters = @scope.filters[item.type]
filter = _.find(filters, {id: item.id})
filter.selected = false
@.unselectFilter(item.type, item.id)
@.loadUserstories()
loadAllPaginatedUserstories: () -> loadAllPaginatedUserstories: () ->
page = @.page page = @.page
@ -272,15 +261,15 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
@.loadingUserstories = true @.loadingUserstories = true
@.disablePagination = true @.disablePagination = true
@scope.httpParams = @.getUrlFilters() params = _.clone(@location.search())
@rs.userstories.storeQueryParams(@scope.projectId, @scope.httpParams) @rs.userstories.storeQueryParams(@scope.projectId, params)
if resetPagination if resetPagination
@.page = 1 @.page = 1
@scope.httpParams.page = @.page params.page = @.page
promise = @rs.userstories.listUnassigned(@scope.projectId, @scope.httpParams, pageSize) promise = @rs.userstories.listUnassigned(@scope.projectId, params, pageSize)
return promise.then (result) => return promise.then (result) =>
userstories = result[0] userstories = result[0]
@ -292,7 +281,8 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
# NOTE: Fix order of USs because the filter orderBy does not work propertly in the partials files # NOTE: Fix order of USs because the filter orderBy does not work propertly in the partials files
@scope.userstories = @scope.userstories.concat(_.sortBy(userstories, "backlog_order")) @scope.userstories = @scope.userstories.concat(_.sortBy(userstories, "backlog_order"))
@.setSearchDataFilters() for it in @scope.userstories
@.backlogOrder[it.id] = it.backlog_order
@.loadingUserstories = false @.loadingUserstories = false
@ -317,7 +307,7 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
loadProject: -> loadProject: ->
return @rs.projects.getBySlug(@params.pslug).then (project) => return @rs.projects.getBySlug(@params.pslug).then (project) =>
if not project.is_backlog_activated if not project.is_backlog_activated
@location.path(@navUrls.resolve("permission-denied")) @errorHandlingService.permissionDenied()
@scope.projectId = project.id @scope.projectId = project.id
@scope.project = project @scope.project = project
@ -343,252 +333,152 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
prepareBulkUpdateData: (uses, field="backlog_order") -> prepareBulkUpdateData: (uses, field="backlog_order") ->
return _.map(uses, (x) -> {"us_id": x.id, "order": x[field]}) return _.map(uses, (x) -> {"us_id": x.id, "order": x[field]})
resortUserStories: (uses, field="backlog_order") -> # --move us api behavior--
items = [] # If your are moving multiples USs you must use the bulk api
# If there is only one US you must use patch (repo.save)
for item, index in uses #
item[field] = index # The new US position is the position of the previous US + 1.
if item.isModified() # If the previous US has a position value that it is equal to
items.push(item) # other USs, you must send all the USs with that position value
# only if they are before of the target position with this USs
return items # if it's a patch you must add them to the header, if is a bulk
# you must send them with the other USs
moveUs: (ctx, usList, newUsIndex, newSprintId) -> moveUs: (ctx, usList, newUsIndex, newSprintId) ->
oldSprintId = usList[0].milestone oldSprintId = usList[0].milestone
project = usList[0].project project = usList[0].project
movedFromClosedSprint = false if oldSprintId
movedToClosedSprint = false sprint = @scope.sprintsById[oldSprintId] || @scope.closedSprintsById[oldSprintId]
sprint = @scope.sprintsById[oldSprintId] if newSprintId
newSprint = @scope.sprintsById[newSprintId] || @scope.closedSprintsById[newSprintId]
# Move from closed sprint currentSprintId = if newSprintId != oldSprintId then newSprintId else oldSprintId
if !sprint && @scope.closedSprintsById
sprint = @scope.closedSprintsById[oldSprintId]
movedFromClosedSprint = true if sprint
newSprint = @scope.sprintsById[newSprintId] orderList = null
orderField = ""
# Move to closed sprint if newSprintId != oldSprintId
if !newSprint && newSprintId if newSprintId == null # From sprint to backlog
newSprint = @scope.closedSprintsById[newSprintId] for us, key in usList # delete from sprint userstories
movedToClosedSprint = true if newSprint _.remove sprint.user_stories, (it) -> it.id == us.id
# In the same sprint or in the backlog orderField = "backlog_order"
if newSprintId == oldSprintId orderList = @.backlogOrder
items = null
userstories = null
if newSprintId == null beforeDestination = _.slice(@scope.userstories, 0, newUsIndex)
userstories = @scope.userstories afterDestination = _.slice(@scope.userstories, newUsIndex)
else
userstories = newSprint.user_stories
@scope.$apply -> @scope.userstories = @scope.userstories.concat(usList)
for us, key in usList else # From backlog to sprint
r = userstories.indexOf(us) for us in usList # delete from sprint userstories
userstories.splice(r, 1) _.remove @scope.userstories, (it) -> it.id == us.id
args = [newUsIndex, 0].concat(usList) orderField = "sprint_order"
Array.prototype.splice.apply(userstories, args) orderList = @.milestonesOrder[newSprint.id]
# If in backlog beforeDestination = _.slice(newSprint.user_stories, 0, newUsIndex)
if newSprintId == null afterDestination = _.slice(newSprint.user_stories, newUsIndex)
# Rehash userstories order field
items = @.resortUserStories(userstories, "backlog_order") newSprint.user_stories = newSprint.user_stories.concat(usList)
data = @.prepareBulkUpdateData(items, "backlog_order")
# Persist in bulk all affected
# userstories with order change
@rs.userstories.bulkUpdateBacklogOrder(project, data).then =>
@rootscope.$broadcast("sprint:us:moved")
# For sprint
else
# Rehash userstories order field
items = @.resortUserStories(userstories, "sprint_order")
data = @.prepareBulkUpdateData(items, "sprint_order")
# Persist in bulk all affected
# userstories with order change
@rs.userstories.bulkUpdateSprintOrder(project, data).then =>
@rootscope.$broadcast("sprint:us:moved")
return promise
# From sprint to backlog
if newSprintId == null
us.milestone = null for us in usList
@scope.$apply =>
# Add new us to backlog userstories list
# @scope.userstories.splice(newUsIndex, 0, us)
args = [newUsIndex, 0].concat(usList)
Array.prototype.splice.apply(@scope.userstories, args)
for us, key in usList
r = sprint.user_stories.indexOf(us)
sprint.user_stories.splice(r, 1)
# Persist the milestone change of userstory
promise = @repo.save(us)
# Rehash userstories order field
# and persist in bulk all changes.
promise = promise.then =>
items = @.resortUserStories(@scope.userstories, "backlog_order")
data = @.prepareBulkUpdateData(items, "backlog_order")
return @rs.userstories.bulkUpdateBacklogOrder(us.project, data).then =>
@rootscope.$broadcast("sprint:us:moved")
if movedFromClosedSprint
@rootscope.$broadcast("backlog:load-closed-sprints")
promise.then null, ->
console.log "FAIL" # TODO
return promise
# From backlog to sprint
if oldSprintId == null
us.milestone = newSprintId for us in usList
args = [newUsIndex, 0].concat(usList)
# Add moving us to sprint user stories list
Array.prototype.splice.apply(newSprint.user_stories, args)
# Remove moving us from backlog userstories lists.
for us, key in usList
r = @scope.userstories.indexOf(us)
@scope.userstories.splice(r, 1)
# From sprint to sprint
else else
us.milestone = newSprintId for us in usList if oldSprintId == null # backlog
orderField = "backlog_order"
orderList = @.backlogOrder
@scope.$apply => list = _.filter @scope.userstories, (listIt) -> # Remove moved US from list
args = [newUsIndex, 0].concat(usList) return !_.find usList, (moveIt) -> return listIt.id == moveIt.id
# Add new us to backlog userstories list beforeDestination = _.slice(list, 0, newUsIndex)
Array.prototype.splice.apply(newSprint.user_stories, args) afterDestination = _.slice(list, newUsIndex)
else # sprint
orderField = "sprint_order"
orderList = @.milestonesOrder[sprint.id]
# Remove the us from the sprint list. list = _.filter newSprint.user_stories, (listIt) -> # Remove moved US from list
for us in usList return !_.find usList, (moveIt) -> return listIt.id == moveIt.id
r = sprint.user_stories.indexOf(us)
sprint.user_stories.splice(r, 1)
#Persist the milestone change of userstory beforeDestination = _.slice(list, 0, newUsIndex)
promises = _.map usList, (us) => @repo.save(us) afterDestination = _.slice(list, newUsIndex)
#Rehash userstories order field # previous us
#and persist in bulk all changes. previous = beforeDestination[beforeDestination.length - 1]
promise = @q.all(promises).then =>
items = @.resortUserStories(newSprint.user_stories, "sprint_order")
data = @.prepareBulkUpdateData(items, "sprint_order")
@rs.userstories.bulkUpdateSprintOrder(project, data).then (result) => # this will store the previous us with the same position
@rootscope.$broadcast("sprint:us:moved") setPreviousOrders = []
@rs.userstories.bulkUpdateBacklogOrder(project, data).then => if !previous
@rootscope.$broadcast("sprint:us:moved") startIndex = 0
else if previous
startIndex = orderList[previous.id] + 1
if movedToClosedSprint || movedFromClosedSprint previousWithTheSameOrder = _.filter(beforeDestination, (it) ->
@scope.$broadcast("backlog:load-closed-sprints") it[orderField] == orderList[previous.id]
)
promise.then null, -> # we must send the USs previous to the dropped USs to tell the backend
console.log "FAIL" # TODO # which USs are before the dropped USs, if they have the same value to
# order, the backend doens't know after which one do you want to drop
# the USs
if previousWithTheSameOrder.length > 1
setPreviousOrders = _.map(previousWithTheSameOrder, (it) ->
{us_id: it.id, order: orderList[it.id]}
)
modifiedUs = []
for us, key in usList # update sprint and new position
us.milestone = currentSprintId
us[orderField] = startIndex + key
orderList[us.id] = us[orderField]
modifiedUs.push({us_id: us.id, order: us[orderField]})
startIndex = orderList[usList[usList.length - 1].id]
for it, key in afterDestination # increase position of the us after the dragged us's
orderList[it.id] = startIndex + key + 1
# refresh order
@scope.userstories = _.sortBy @scope.userstories, (it) => @.backlogOrder[it.id]
for sprint in @scope.sprints
sprint.user_stories = _.sortBy sprint.user_stories, (it) => @.milestonesOrder[sprint.id][it.id]
for sprint in @scope.closedSprints
sprint.user_stories = _.sortBy sprint.user_stories, (it) => @.milestonesOrder[sprint.id][it.id]
# saving
if usList.length > 1 && (newSprintId != oldSprintId) # drag multiple to sprint
data = modifiedUs.concat(setPreviousOrders)
promise = @rs.userstories.bulkUpdateMilestone(project, newSprintId, data)
else if usList.length > 1 # drag multiple in backlog
data = modifiedUs.concat(setPreviousOrders)
promise = @rs.userstories.bulkUpdateBacklogOrder(project, data)
else # drag single
setOrders = {}
for it in setPreviousOrders
setOrders[it.us_id] = it.order
options = {
headers: {
"set-orders": JSON.stringify(setOrders)
}
}
promise = @repo.save(usList[0], true, {}, options, true)
promise.then () =>
@rootscope.$broadcast("sprint:us:moved")
if @scope.closedSprintsById && @scope.closedSprintsById[oldSprintId]
@rootscope.$broadcast("backlog:load-closed-sprints")
return promise return promise
isFilterSelected: (type, id) ->
if @searchdata[type]? and @searchdata[type][id]
return true
return false
setSearchDataFilters: () ->
urlfilters = @.getUrlFilters()
if urlfilters.q
@scope.filtersQ = @scope.filtersQ or urlfilters.q
@searchdata = {}
for name, value of urlfilters
if not @searchdata[name]?
@searchdata[name] = {}
for val in taiga.toString(value).split(",")
@searchdata[name][val] = true
getUrlFilters: ->
return _.pick(@location.search(), "status", "tags", "q")
generateFilters: ->
urlfilters = @.getUrlFilters()
@scope.filters = {}
loadFilters = {}
loadFilters.project = @scope.projectId
loadFilters.tags = urlfilters.tags
loadFilters.status = urlfilters.status
loadFilters.q = urlfilters.q
loadFilters.milestone = 'null'
return @rs.userstories.filtersData(loadFilters).then (data) =>
choicesFiltersFormat = (choices, type, byIdObject) =>
_.map choices, (t) ->
t.type = type
return t
tagsFilterFormat = (tags) =>
return _.map tags, (t) ->
t.id = t.name
t.type = 'tags'
return t
# Build filters data structure
@scope.filters.status = choicesFiltersFormat(data.statuses, "status", @scope.usStatusById)
@scope.filters.tags = tagsFilterFormat(data.tags)
selectedTags = _.filter(@scope.filters.tags, "selected")
selectedTags = _.map(selectedTags, "id")
selectedStatuses = _.filter(@scope.filters.status, "selected")
selectedStatuses = _.map(selectedStatuses, "id")
@.markSelectedFilters(@scope.filters, urlfilters)
#store query params
@rs.userstories.storeQueryParams(@scope.projectId, {
"status": selectedStatuses,
"tags": selectedTags,
"project": @scope.projectId
"milestone": null
})
markSelectedFilters: (filters, urlfilters) ->
# Build selected filters (from url) fast lookup data structure
searchdata = {}
for name, value of _.omit(urlfilters, "page", "orderBy")
if not searchdata[name]?
searchdata[name] = {}
for val in "#{value}".split(",")
searchdata[name][val] = true
isSelected = (type, id) ->
if searchdata[type]? and searchdata[type][id]
return true
return false
for key, value of filters
for obj in value
obj.selected = if isSelected(obj.type, obj.id) then true else undefined
## Template actions ## Template actions
updateUserStoryStatus: () -> updateUserStoryStatus: () ->
@.setSearchDataFilters()
@.generateFilters().then () => @.generateFilters().then () =>
@rootscope.$broadcast("filters:update") @rootscope.$broadcast("filters:update")
@.loadProjectStats() @.loadProjectStats()
@ -641,10 +531,10 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
currentDate = new Date().getTime() currentDate = new Date().getTime()
return _.find @scope.sprints, (sprint) -> return _.find @scope.sprints, (sprint) ->
start = moment(sprint.estimated_start, 'YYYY-MM-DD').format('x') start = moment(sprint.estimated_start, 'YYYY-MM-DD').format('x')
end = moment(sprint.estimated_finish, 'YYYY-MM-DD').format('x') end = moment(sprint.estimated_finish, 'YYYY-MM-DD').format('x')
return currentDate >= start && currentDate <= end return currentDate >= start && currentDate <= end
module.controller("BacklogController", BacklogController) module.controller("BacklogController", BacklogController)
@ -806,8 +696,15 @@ BacklogDirective = ($repo, $rootscope, $translate) ->
text = $translate.instant("BACKLOG.TAGS.SHOW") text = $translate.instant("BACKLOG.TAGS.SHOW")
elm.text(text) elm.text(text)
openFilterInit = ($scope, $el, $ctrl) ->
sidebar = $el.find("sidebar.backlog-filter")
sidebar.addClass("active")
$ctrl.activeFilters = true
showHideFilter = ($scope, $el, $ctrl) -> showHideFilter = ($scope, $el, $ctrl) ->
sidebar = $el.find("sidebar.filters-bar") sidebar = $el.find("sidebar.backlog-filter")
sidebar.one "transitionend", () -> sidebar.one "transitionend", () ->
timeout 150, -> timeout 150, ->
$rootscope.$broadcast("resize") $rootscope.$broadcast("resize")
@ -823,11 +720,6 @@ BacklogDirective = ($repo, $rootscope, $translate) ->
toggleText(target, [hideText, showText]) toggleText(target, [hideText, showText])
if !sidebar.hasClass("active")
$ctrl.resetFilters()
else
$ctrl.restoreFilters()
$ctrl.toggleActiveFilters() $ctrl.toggleActiveFilters()
## Filters Link ## Filters Link
@ -846,11 +738,13 @@ BacklogDirective = ($repo, $rootscope, $translate) ->
linkFilters($scope, $el, $attrs, $ctrl) linkFilters($scope, $el, $attrs, $ctrl)
linkDoomLine($scope, $el, $attrs, $ctrl) linkDoomLine($scope, $el, $attrs, $ctrl)
filters = $ctrl.getUrlFilters() filters = $ctrl.location.search()
if filters.status || if filters.status ||
filters.tags || filters.tags ||
filters.q filters.q ||
showHideFilter($scope, $el, $ctrl) filters.assigned_to ||
filters.owner
openFilterInit($scope, $el, $ctrl)
$scope.$on "showTags", () -> $scope.$on "showTags", () ->
showHideTags($ctrl) showHideTags($ctrl)

View File

@ -23,16 +23,10 @@
### ###
taiga = @.taiga taiga = @.taiga
mixOf = @.taiga.mixOf
toggleText = @.taiga.toggleText
scopeDefer = @.taiga.scopeDefer
bindOnce = @.taiga.bindOnce bindOnce = @.taiga.bindOnce
groupBy = @.taiga.groupBy
module = angular.module("taigaBacklog") module = angular.module("taigaBacklog")
############################################################################# #############################################################################
## Sortable Directive ## Sortable Directive
############################################################################# #############################################################################
@ -42,7 +36,7 @@ deleteElement = (el) ->
$(el).off() $(el).off()
$(el).remove() $(el).remove()
BacklogSortableDirective = ($repo, $rs, $rootscope, $tgConfirm, $translate) -> BacklogSortableDirective = () ->
link = ($scope, $el, $attrs) -> link = ($scope, $el, $attrs) ->
bindOnce $scope, "project", (project) -> bindOnce $scope, "project", (project) ->
# If the user has not enough permissions we don't enable the sortable # If the user has not enough permissions we don't enable the sortable
@ -51,10 +45,6 @@ BacklogSortableDirective = ($repo, $rs, $rootscope, $tgConfirm, $translate) ->
initIsBacklog = false initIsBacklog = false
filterError = ->
text = $translate.instant("BACKLOG.SORTABLE_FILTER_ERROR")
$tgConfirm.notify("error", text)
drake = dragula([$el[0], $('.empty-backlog')[0]], { drake = dragula([$el[0], $('.empty-backlog')[0]], {
copySortSource: false, copySortSource: false,
copy: false, copy: false,
@ -63,18 +53,11 @@ BacklogSortableDirective = ($repo, $rs, $rootscope, $tgConfirm, $translate) ->
if !$(item).hasClass('row') if !$(item).hasClass('row')
return false return false
# it doesn't move is the filter is open
parent = $(item).parent()
initIsBacklog = parent.hasClass('backlog-table-body')
if initIsBacklog && $el.hasClass("active-filters")
filterError()
return false
return true return true
}) })
drake.on 'drag', (item, container) -> drake.on 'drag', (item, container) ->
# it doesn't move is the filter is open
parent = $(item).parent() parent = $(item).parent()
initIsBacklog = parent.hasClass('backlog-table-body') initIsBacklog = parent.hasClass('backlog-table-body')
@ -88,6 +71,8 @@ BacklogSortableDirective = ($repo, $rs, $rootscope, $tgConfirm, $translate) ->
$(item).addClass('backlog-us-mirror') $(item).addClass('backlog-us-mirror')
drake.on 'dragend', (item) -> drake.on 'dragend', (item) ->
parent = $(item).parent()
$('.doom-line').remove() $('.doom-line').remove()
parent = $(item).parent() parent = $(item).parent()
@ -102,8 +87,6 @@ BacklogSortableDirective = ($repo, $rs, $rootscope, $tgConfirm, $translate) ->
$(document.body).removeClass("drag-active") $(document.body).removeClass("drag-active")
items = $(item).parent().find('.row')
sprint = null sprint = null
firstElement = if dragMultipleItems.length then dragMultipleItems[0] else item firstElement = if dragMultipleItems.length then dragMultipleItems[0] else item
@ -131,11 +114,7 @@ BacklogSortableDirective = ($repo, $rs, $rootscope, $tgConfirm, $translate) ->
usList = _.map dragMultipleItems, (item) -> usList = _.map dragMultipleItems, (item) ->
return item = $(item).scope().us return item = $(item).scope().us
else else
usList = _.map items, (item) -> usList = [$(item).scope().us]
item = $(item)
itemUs = item.scope().us
return itemUs
$scope.$emit("sprint:us:move", usList, index, sprint) $scope.$emit("sprint:us:move", usList, index, sprint)
@ -144,7 +123,7 @@ BacklogSortableDirective = ($repo, $rs, $rootscope, $tgConfirm, $translate) ->
pixels: 30, pixels: 30,
scrollWhenOutside: true, scrollWhenOutside: true,
autoScroll: () -> autoScroll: () ->
return this.down && drake.dragging; return this.down && drake.dragging
}) })
$scope.$on "$destroy", -> $scope.$on "$destroy", ->
@ -153,11 +132,4 @@ BacklogSortableDirective = ($repo, $rs, $rootscope, $tgConfirm, $translate) ->
return {link: link} return {link: link}
module.directive("tgBacklogSortable", [ module.directive("tgBacklogSortable", BacklogSortableDirective)
"$tgRepo",
"$tgResources",
"$rootScope",
"$tgConfirm",
"$translate",
BacklogSortableDirective
])

View File

@ -73,13 +73,16 @@ urls = {
"project-taskboard": "/project/:project/taskboard/:sprint" "project-taskboard": "/project/:project/taskboard/:sprint"
"project-kanban": "/project/:project/kanban" "project-kanban": "/project/:project/kanban"
"project-issues": "/project/:project/issues" "project-issues": "/project/:project/issues"
"project-epics": "/project/:project/epics"
"project-search": "/project/:project/search" "project-search": "/project/:project/search"
"project-epics-detail": "/project/:project/epic/:ref"
"project-userstories-detail": "/project/:project/us/:ref" "project-userstories-detail": "/project/:project/us/:ref"
"project-tasks-detail": "/project/:project/task/:ref" "project-tasks-detail": "/project/:project/task/:ref"
"project-issues-detail": "/project/:project/issue/:ref" "project-issues-detail": "/project/:project/issue/:ref"
"project-wiki": "/project/:project/wiki" "project-wiki": "/project/:project/wiki"
"project-wiki-list": "/project/:project/wiki-list"
"project-wiki-page": "/project/:project/wiki/:slug" "project-wiki-page": "/project/:project/wiki/:slug"
# Team # Team
@ -99,6 +102,7 @@ urls = {
"project-admin-project-values-severities": "/project/:project/admin/project-values/severities" "project-admin-project-values-severities": "/project/:project/admin/project-values/severities"
"project-admin-project-values-types": "/project/:project/admin/project-values/types" "project-admin-project-values-types": "/project/:project/admin/project-values/types"
"project-admin-project-values-custom-fields": "/project/:project/admin/project-values/custom-fields" "project-admin-project-values-custom-fields": "/project/:project/admin/project-values/custom-fields"
"project-admin-project-values-tags": "/project/:project/admin/project-values/tags"
"project-admin-memberships": "/project/:project/admin/memberships" "project-admin-memberships": "/project/:project/admin/memberships"
"project-admin-roles": "/project/:project/admin/roles" "project-admin-roles": "/project/:project/admin/roles"
@ -106,6 +110,7 @@ urls = {
"project-admin-third-parties-github": "/project/:project/admin/third-parties/github" "project-admin-third-parties-github": "/project/:project/admin/third-parties/github"
"project-admin-third-parties-gitlab": "/project/:project/admin/third-parties/gitlab" "project-admin-third-parties-gitlab": "/project/:project/admin/third-parties/gitlab"
"project-admin-third-parties-bitbucket": "/project/:project/admin/third-parties/bitbucket" "project-admin-third-parties-bitbucket": "/project/:project/admin/third-parties/bitbucket"
"project-admin-third-parties-gogs": "/project/:project/admin/third-parties/gogs"
"project-admin-contrib": "/project/:project/admin/contrib/:plugin" "project-admin-contrib": "/project/:project/admin/contrib/:plugin"
# User settings # User settings

View File

@ -30,7 +30,7 @@ class HttpService extends taiga.Service
constructor: (@http, @q, @storage, @rootScope, @cacheFactory, @translate) -> constructor: (@http, @q, @storage, @rootScope, @cacheFactory, @translate) ->
super() super()
@.cache = @cacheFactory("httpget"); @.cache = @cacheFactory("httpget")
headers: -> headers: ->
headers = {} headers = {}

View File

@ -41,7 +41,7 @@ class RepositoryService extends taiga.Service
defered = @q.defer() defered = @q.defer()
url = @urls.resolve(name) url = @urls.resolve(name)
promise = @http.post(url, JSON.stringify(data)) promise = @http.post(url, JSON.stringify(data), extraParams)
promise.success (_data, _status) => promise.success (_data, _status) =>
defered.resolve(@model.make_model(name, _data, null, dataTypes)) defered.resolve(@model.make_model(name, _data, null, dataTypes))
@ -67,7 +67,7 @@ class RepositoryService extends taiga.Service
promises = _.map(models, (x) => @.save(x, true)) promises = _.map(models, (x) => @.save(x, true))
return @q.all(promises) return @q.all(promises)
save: (model, patch=true) -> save: (model, patch=true, params = {}, options, returnHeaders = false) ->
defered = @q.defer() defered = @q.defer()
if not model.isModified() and patch if not model.isModified() and patch
@ -75,20 +75,25 @@ class RepositoryService extends taiga.Service
return defered.promise return defered.promise
url = @.resolveUrlForModel(model) url = @.resolveUrlForModel(model)
data = JSON.stringify(model.getAttrs(patch)) data = JSON.stringify(model.getAttrs(patch))
if patch if patch
promise = @http.patch(url, data) promise = @http.patch(url, data, params, options)
else else
promise = @http.put(url, data) promise = @http.put(url, data, params, options)
promise.success (data, status) => promise.success (data, status, headers, response) =>
model._isModified = false model._isModified = false
model._attrs = _.extend(model.getAttrs(), data) model._attrs = _.extend(model.getAttrs(), data)
model._modifiedAttrs = {} model._modifiedAttrs = {}
model.applyCasts() model.applyCasts()
defered.resolve(model)
if returnHeaders
defered.resolve([model, headers()])
else
defered.resolve(model)
promise.error (data, status) -> promise.error (data, status) ->
defered.reject(data) defered.reject(data)

View File

@ -398,3 +398,50 @@ Autofocus = ($timeout) ->
} }
module.directive('tgAutofocus', ['$timeout', Autofocus]) module.directive('tgAutofocus', ['$timeout', Autofocus])
module.directive 'tgPreloadImage', () ->
spinner = "<img class='loading-spinner' src='/" + window._version + "/svg/spinner-circle.svg' alt='loading...' />"
template = """
<div>
<ng-transclude></ng-transclude>
</div>
"""
preload = (src, onLoad) ->
image = new Image()
image.onload = onLoad
image.src = src
return image
return {
template: template,
transclude: true,
replace: true,
link: (scope, el, attrs) ->
image = el.find('img:last')
timeout = null
onLoad = () ->
el.find('.loading-spinner').remove()
image.show()
if timeout
clearTimeout(timeout)
timeout = null
attrs.$observe 'preloadSrc', (src) ->
if timeout
clearTimeout(timeout)
el.find('.loading-spinner').remove()
timeout = setTimeout () ->
el.prepend(spinner)
, 200
image.hide()
preload(src, onLoad)
}

View File

@ -126,7 +126,7 @@ module.directive("tgSprintProgressbar", SprintProgressBarDirective)
## Created-by display directive ## Created-by display directive
############################################################################# #############################################################################
CreatedByDisplayDirective = ($template, $compile, $translate, $navUrls)-> CreatedByDisplayDirective = ($template, $compile, $translate, $navUrls, avatarService)->
# Display the owner information (full name and photo) and the date of # Display the owner information (full name and photo) and the date of
# creation of an object (like USs, tasks and issues). # creation of an object (like USs, tasks and issues).
# #
@ -141,11 +141,15 @@ CreatedByDisplayDirective = ($template, $compile, $translate, $navUrls)->
link = ($scope, $el, $attrs) -> link = ($scope, $el, $attrs) ->
bindOnce $scope, $attrs.ngModel, (model) -> bindOnce $scope, $attrs.ngModel, (model) ->
if model? if model?
avatar = avatarService.getAvatar(model.owner_extra_info)
$scope.owner = model.owner_extra_info or { $scope.owner = model.owner_extra_info or {
full_name_display: $translate.instant("COMMON.EXTERNAL_USER") full_name_display: $translate.instant("COMMON.EXTERNAL_USER")
photo: "/" + window._version + "/images/user-noimage.png"
} }
$scope.owner.avatar = avatar.url
$scope.owner.bg = avatar.bg
$scope.url = if $scope.owner?.is_active then $navUrls.resolve("user-profile", {username: $scope.owner.username}) else "" $scope.url = if $scope.owner?.is_active then $navUrls.resolve("user-profile", {username: $scope.owner.username}) else ""
@ -162,9 +166,45 @@ CreatedByDisplayDirective = ($template, $compile, $translate, $navUrls)->
templateUrl: "common/components/created-by.html" templateUrl: "common/components/created-by.html"
} }
module.directive("tgCreatedByDisplay", ["$tgTemplate", "$compile", "$translate", "$tgNavUrls", module.directive("tgCreatedByDisplay", ["$tgTemplate", "$compile", "$translate", "$tgNavUrls", "tgAvatarService",
CreatedByDisplayDirective]) CreatedByDisplayDirective])
UserDisplayDirective = ($template, $compile, $translate, $navUrls, avatarService)->
# Display the user information (full name and photo).
#
# Example:
# div.creator(tg-user-display, tg-user-id="{{ user.id }}")
#
# Requirements:
# - scope.usersById object is required.
link = ($scope, $el, $attrs) ->
id = $attrs.tgUserId
$scope.user = $scope.usersById[id] or {
full_name_display: $translate.instant("COMMON.EXTERNAL_USER")
}
avatar = avatarService.getAvatar($scope.usersById[id] or null)
$scope.user.avatar = avatar.url
$scope.user.bg = avatar.bg
$scope.url = if $scope.user.is_active then $navUrls.resolve("user-profile", {username: $scope.user.username}) else ""
$scope.$on "$destroy", ->
$el.off()
return {
link: link
restrict: "EA"
scope: true,
templateUrl: "common/components/user-display.html"
}
module.directive("tgUserDisplay", ["$tgTemplate", "$compile", "$translate", "$tgNavUrls", "tgAvatarService",
UserDisplayDirective])
############################################################################# #############################################################################
## Watchers directive ## Watchers directive
############################################################################# #############################################################################
@ -172,7 +212,6 @@ module.directive("tgCreatedByDisplay", ["$tgTemplate", "$compile", "$translate",
WatchersDirective = ($rootscope, $confirm, $repo, $modelTransform, $template, $compile, $translate) -> WatchersDirective = ($rootscope, $confirm, $repo, $modelTransform, $template, $compile, $translate) ->
# You have to include a div with the tg-lb-watchers directive in the page # You have to include a div with the tg-lb-watchers directive in the page
# where use this directive # where use this directive
template = $template.get("common/components/watchers.html", true)
link = ($scope, $el, $attrs, $model) -> link = ($scope, $el, $attrs, $model) ->
isEditable = -> isEditable = ->
@ -209,13 +248,8 @@ WatchersDirective = ($rootscope, $confirm, $repo, $modelTransform, $template, $c
$confirm.notify("error") $confirm.notify("error")
renderWatchers = (watchers) -> renderWatchers = (watchers) ->
ctx = { $scope.watchers = watchers
watchers: watchers $scope.isEditable = isEditable()
isEditable: isEditable()
}
html = $compile(template(ctx))($scope)
$el.html(html)
$el.on "click", ".js-delete-watcher", (event) -> $el.on "click", ".js-delete-watcher", (event) ->
event.preventDefault() event.preventDefault()
@ -244,12 +278,19 @@ WatchersDirective = ($rootscope, $confirm, $repo, $modelTransform, $template, $c
$scope.$watch $attrs.ngModel, (item) -> $scope.$watch $attrs.ngModel, (item) ->
return if not item? return if not item?
watchers = _.map(item.watchers, (watcherId) -> $scope.usersById[watcherId]) watchers = _.map(item.watchers, (watcherId) -> $scope.usersById[watcherId])
watchers = _.filter watchers, (it) -> return !!it
renderWatchers(watchers) renderWatchers(watchers)
$scope.$on "$destroy", -> $scope.$on "$destroy", ->
$el.off() $el.off()
return {link:link, require:"ngModel"} return {
scope: true,
templateUrl: "common/components/watchers.html",
link:link,
require:"ngModel"
}
module.directive("tgWatchers", ["$rootScope", "$tgConfirm", "$tgRepo", "$tgQueueModelTransformation", "$tgTemplate", "$compile", module.directive("tgWatchers", ["$rootScope", "$tgConfirm", "$tgRepo", "$tgQueueModelTransformation", "$tgTemplate", "$compile",
"$translate", WatchersDirective]) "$translate", WatchersDirective])
@ -259,7 +300,7 @@ module.directive("tgWatchers", ["$rootScope", "$tgConfirm", "$tgRepo", "$tgQueue
## Assigned to directive ## Assigned to directive
############################################################################# #############################################################################
AssignedToDirective = ($rootscope, $confirm, $repo, $loading, $modelTransform, $template, $translate, $compile, $currentUserService) -> AssignedToDirective = ($rootscope, $confirm, $repo, $loading, $modelTransform, $template, $translate, $compile, $currentUserService, avatarService) ->
# You have to include a div with the tg-lb-assignedto directive in the page # You have to include a div with the tg-lb-assignedto directive in the page
# where use this directive # where use this directive
template = $template.get("common/components/assigned-to.html", true) template = $template.get("common/components/assigned-to.html", true)
@ -293,20 +334,23 @@ AssignedToDirective = ($rootscope, $confirm, $repo, $loading, $modelTransform, $
return transform return transform
renderAssignedTo = (assignedObject) -> renderAssignedTo = (assignedObject) ->
avatar = avatarService.getAvatar(assignedObject?.assigned_to_extra_info)
bg = null
if assignedObject?.assigned_to? if assignedObject?.assigned_to?
fullName = assignedObject.assigned_to_extra_info.full_name_display fullName = assignedObject.assigned_to_extra_info.full_name_display
photo = assignedObject.assigned_to_extra_info.photo
isUnassigned = false isUnassigned = false
bg = avatar.bg
else else
fullName = $translate.instant("COMMON.ASSIGNED_TO.ASSIGN") fullName = $translate.instant("COMMON.ASSIGNED_TO.ASSIGN")
photo = "/#{window._version}/images/unnamed.png"
isUnassigned = true isUnassigned = true
isIocaine = assignedObject?.is_iocaine isIocaine = assignedObject?.is_iocaine
ctx = { ctx = {
fullName: fullName fullName: fullName
photo: photo avatar: avatar.url
bg: bg
isUnassigned: isUnassigned isUnassigned: isUnassigned
isEditable: isEditable() isEditable: isEditable()
isIocaine: isIocaine isIocaine: isIocaine
@ -353,7 +397,7 @@ AssignedToDirective = ($rootscope, $confirm, $repo, $loading, $modelTransform, $
require:"ngModel" require:"ngModel"
} }
module.directive("tgAssignedTo", ["$rootScope", "$tgConfirm", "$tgRepo", "$tgLoading", "$tgQueueModelTransformation", "$tgTemplate", "$translate", "$compile","tgCurrentUserService", module.directive("tgAssignedTo", ["$rootScope", "$tgConfirm", "$tgRepo", "$tgLoading", "$tgQueueModelTransformation", "$tgTemplate", "$translate", "$compile","tgCurrentUserService", "tgAvatarService",
AssignedToDirective]) AssignedToDirective])
@ -448,93 +492,6 @@ DeleteButtonDirective = ($log, $repo, $confirm, $location, $template) ->
module.directive("tgDeleteButton", ["$log", "$tgRepo", "$tgConfirm", "$tgLocation", "$tgTemplate", DeleteButtonDirective]) module.directive("tgDeleteButton", ["$log", "$tgRepo", "$tgConfirm", "$tgLocation", "$tgTemplate", DeleteButtonDirective])
#############################################################################
## Editable subject directive
#############################################################################
EditableSubjectDirective = ($rootscope, $repo, $confirm, $loading, $modelTransform, $template) ->
template = $template.get("common/components/editable-subject.html")
link = ($scope, $el, $attrs, $model) ->
$scope.$on "object:updated", () ->
$el.find('.edit-subject').hide()
$el.find('.view-subject').show()
isEditable = ->
return $scope.project.my_permissions.indexOf($attrs.requiredPerm) != -1
save = (subject) ->
currentLoading = $loading()
.target($el.find('.save-container'))
.start()
transform = $modelTransform.save (item) ->
item.subject = subject
return item
transform.then =>
$confirm.notify("success")
$rootscope.$broadcast("object:updated")
$el.find('.edit-subject').hide()
$el.find('.view-subject').show()
transform.then null, ->
$confirm.notify("error")
transform.finally ->
currentLoading.finish()
return transform
$el.click ->
return if not isEditable()
$el.find('.edit-subject').show()
$el.find('.view-subject').hide()
$el.find('input').focus()
$el.on "click", ".save", (e) ->
e.preventDefault()
subject = $scope.item.subject
save(subject)
$el.on "keyup", "input", (event) ->
if event.keyCode == 13
subject = $scope.item.subject
save(subject)
else if event.keyCode == 27
$scope.$apply () => $model.$modelValue.revert()
$el.find('.edit-subject').hide()
$el.find('.view-subject').show()
$el.find('.edit-subject').hide()
$scope.$watch $attrs.ngModel, (value) ->
return if not value
$scope.item = value
if not isEditable()
$el.find('.view-subject .edit').remove()
$scope.$on "$destroy", ->
$el.off()
return {
link: link
restrict: "EA"
require: "ngModel"
template: template
}
module.directive("tgEditableSubject", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgLoading", "$tgQueueModelTransformation",
"$tgTemplate", EditableSubjectDirective])
############################################################################# #############################################################################
## Editable description directive ## Editable description directive
############################################################################# #############################################################################
@ -656,7 +613,7 @@ EditableWysiwyg = (attachmentsService, attachmentsFullService) ->
link = ($scope, $el, $attrs, $model) -> link = ($scope, $el, $attrs, $model) ->
isInEditMode = -> isInEditMode = ->
return $el.find('textarea').is(':visible') return $el.find('textarea').is(':visible') and $model.$modelValue.id
uploadFile = (file, type) -> uploadFile = (file, type) ->
@ -721,6 +678,16 @@ module.directive("tgEditableWysiwyg", ["tgAttachmentsService", "tgAttachmentsFul
## completely bindonce, they only serves for visualization of data. ## completely bindonce, they only serves for visualization of data.
############################################################################# #############################################################################
ListItemEpicStatusDirective = ->
link = ($scope, $el, $attrs) ->
epic = $scope.$eval($attrs.tgListitemEpicStatus)
bindOnce $scope, "epicStatusById", (epicStatusById) ->
$el.html(epicStatusById[epic.status].name)
return {link:link}
module.directive("tgListitemEpicStatus", ListItemEpicStatusDirective)
ListItemUsStatusDirective = -> ListItemUsStatusDirective = ->
link = ($scope, $el, $attrs) -> link = ($scope, $el, $attrs) ->
us = $scope.$eval($attrs.tgListitemUsStatus) us = $scope.$eval($attrs.tgListitemUsStatus)
@ -743,7 +710,7 @@ ListItemTaskStatusDirective = ->
module.directive("tgListitemTaskStatus", ListItemTaskStatusDirective) module.directive("tgListitemTaskStatus", ListItemTaskStatusDirective)
ListItemAssignedtoDirective = ($template, $translate) -> ListItemAssignedtoDirective = ($template, $translate, avatarService) ->
template = $template.get("common/components/list-item-assigned-to-avatar.html", true) template = $template.get("common/components/list-item-assigned-to-avatar.html", true)
link = ($scope, $el, $attrs) -> link = ($scope, $el, $attrs) ->
@ -751,19 +718,22 @@ ListItemAssignedtoDirective = ($template, $translate) ->
item = $scope.$eval($attrs.tgListitemAssignedto) item = $scope.$eval($attrs.tgListitemAssignedto)
ctx = { ctx = {
name: $translate.instant("COMMON.ASSIGNED_TO.NOT_ASSIGNED"), name: $translate.instant("COMMON.ASSIGNED_TO.NOT_ASSIGNED"),
imgurl: "/#{window._version}/images/unnamed.png"
} }
member = usersById[item.assigned_to] member = usersById[item.assigned_to]
avatar = avatarService.getAvatar(member)
ctx.imgurl = avatar.url
ctx.bg = avatar.bg
if member if member
ctx.imgurl = member.photo
ctx.name = member.full_name_display ctx.name = member.full_name_display
$el.html(template(ctx)) $el.html(template(ctx))
return {link:link} return {link:link}
module.directive("tgListitemAssignedto", ["$tgTemplate", "$translate", ListItemAssignedtoDirective]) module.directive("tgListitemAssignedto", ["$tgTemplate", "$translate", "tgAvatarService", ListItemAssignedtoDirective])
ListItemIssueStatusDirective = -> ListItemIssueStatusDirective = ->

View File

@ -112,31 +112,23 @@ CustomAttributesValuesDirective = ($templates, $storage) ->
link = ($scope, $el, $attrs, $ctrls) -> link = ($scope, $el, $attrs, $ctrls) ->
$ctrl = $ctrls[0] $ctrl = $ctrls[0]
$model = $ctrls[1] $model = $ctrls[1]
hash = collapsedHash($attrs.type)
$scope.collapsed = $storage.get(hash) or false
bindOnce $scope, $attrs.ngModel, (value) -> bindOnce $scope, $attrs.ngModel, (value) ->
$ctrl.initialize($attrs.type, value.id) $ctrl.initialize($attrs.type, value.id)
$ctrl.loadCustomAttributesValues() $ctrl.loadCustomAttributesValues()
$el.on "click", ".custom-fields-header .collapse", -> $scope.toggleCollapse = () ->
hash = collapsedHash($attrs.type) $scope.collapsed = !$scope.collapsed
collapsed = not($storage.get(hash) or false) $storage.set(hash, $scope.collapsed)
$storage.set(hash, collapsed)
if collapsed
$el.find(".custom-fields-header .icon").removeClass("open")
$el.find(".custom-fields-body").removeClass("open")
else
$el.find(".custom-fields-header .icon").addClass("open")
$el.find(".custom-fields-body").addClass("open")
$scope.$on "$destroy", -> $scope.$on "$destroy", ->
$el.off() $el.off()
templateFn = ($el, $attrs) -> templateFn = ($el, $attrs) ->
collapsed = $storage.get(collapsedHash($attrs.type)) or false
return template({ return template({
requiredEditionPerm: $attrs.requiredEditionPerm requiredEditionPerm: $attrs.requiredEditionPerm
collapsed: collapsed
}) })
return { return {

View File

@ -57,6 +57,7 @@ LbUsEstimationDirective = ($tgEstimationsService, $rootScope, $repo, $template,
totalPoints: @calculateTotalPoints() totalPoints: @calculateTotalPoints()
roles: @calculateRoles() roles: @calculateRoles()
editable: @isEditable editable: @isEditable
loading: false
} }
mainTemplate = "common/estimation/us-estimation-points-per-role.html" mainTemplate = "common/estimation/us-estimation-points-per-role.html"
template = $template.get(mainTemplate, true) template = $template.get(mainTemplate, true)
@ -111,14 +112,19 @@ UsEstimationDirective = ($tgEstimationsService, $rootScope, $repo, $template, $c
if us if us
estimationProcess = $tgEstimationsService.create($el, us, $scope.project) estimationProcess = $tgEstimationsService.create($el, us, $scope.project)
estimationProcess.onSelectedPointForRole = (roleId, pointId, points) -> estimationProcess.onSelectedPointForRole = (roleId, pointId, points) ->
estimationProcess.loading = roleId
estimationProcess.render()
save(points).then () -> save(points).then () ->
estimationProcess.loading = false
$rootScope.$broadcast("object:updated") $rootScope.$broadcast("object:updated")
estimationProcess.render()
estimationProcess.render = () -> estimationProcess.render = () ->
ctx = { ctx = {
totalPoints: @calculateTotalPoints() totalPoints: @calculateTotalPoints()
roles: @calculateRoles() roles: @calculateRoles()
editable: @isEditable editable: @isEditable
loading: estimationProcess.loading
} }
mainTemplate = "common/estimation/us-estimation-points-per-role.html" mainTemplate = "common/estimation/us-estimation-points-per-role.html"
template = $template.get(mainTemplate, true) template = $template.get(mainTemplate, true)
@ -154,6 +160,7 @@ EstimationsService = ($template, $repo, $confirm, $q, $qqueue) ->
@isEditable = @project.my_permissions.indexOf("modify_us") != -1 @isEditable = @project.my_permissions.indexOf("modify_us") != -1
@roles = @project.roles @roles = @project.roles
@points = @project.points @points = @project.points
@loading = false
@pointsById = groupBy(@points, (x) -> x.id) @pointsById = groupBy(@points, (x) -> x.id)
@onSelectedPointForRole = (roleId, pointId) -> @onSelectedPointForRole = (roleId, pointId) ->
@render = () -> @render = () ->
@ -163,6 +170,7 @@ EstimationsService = ($template, $repo, $confirm, $q, $qqueue) ->
$qqueue.add () => $qqueue.add () =>
onSuccess = => onSuccess = =>
deferred.resolve() deferred.resolve()
@render()
onError = => onError = =>
$confirm.notify("error") $confirm.notify("error")
@ -215,7 +223,6 @@ EstimationsService = ($template, $repo, $confirm, $q, $qqueue) ->
pointId = target.data("point-id") pointId = target.data("point-id")
@$el.find(".popover").popover().close() @$el.find(".popover").popover().close()
points = _.clone(@us.points, true) points = _.clone(@us.points, true)
points[roleId] = pointId points[roleId] = pointId

View File

@ -74,3 +74,56 @@ sizeFormat = =>
return @.taiga.sizeFormat return @.taiga.sizeFormat
module.filter("sizeFormat", sizeFormat) module.filter("sizeFormat", sizeFormat)
toMutableFilter = ->
toMutable = (js) ->
return js.toJS()
memoizedMutable = _.memoize(toMutable)
return (input) ->
if input instanceof Immutable.List
return memoizedMutable(input)
return input
module.filter("toMutable", toMutableFilter)
byRefFilter = ($filterFilter)->
return (userstories, filter) ->
if filter?.startsWith("#")
cleanRef= filter.substr(1)
return _.filter(userstories, (us) => String(us.ref).startsWith(cleanRef))
return $filterFilter(userstories, filter)
module.filter("byRef", ["filterFilter", byRefFilter])
darkerFilter = ->
return (color, luminosity) ->
# validate hex string
color = new String(color).replace(/[^0-9a-f]/gi, '')
if color.length < 6
color = color[0]+ color[0]+ color[1]+ color[1]+ color[2]+ color[2];
luminosity = luminosity || 0
# convert to decimal and change luminosity
newColor = "#"
c = 0
i = 0
black = 0
white = 255
# for (i = 0; i < 3; i++)
for i in [0, 1, 2]
c = parseInt(color.substr(i*2,2), 16)
c = Math.round(Math.min(Math.max(black, c + (luminosity * white)), white)).toString(16)
newColor += ("00"+c).substr(c.length)
return newColor
module.filter("darker", darkerFilter)

View File

@ -1,507 +0,0 @@
###
# Copyright (C) 2014-2016 Andrey Antukh <niwi@niwi.nz>
# Copyright (C) 2014-2016 Jesús Espino Garcia <jespinog@gmail.com>
# Copyright (C) 2014-2016 David Barragán Merino <bameda@dbarragan.com>
# Copyright (C) 2014-2016 Alejandro Alonso <alejandro.alonso@kaleidos.net>
# Copyright (C) 2014-2016 Juan Francisco Alcántara <juanfran.alcantara@kaleidos.net>
# Copyright (C) 2014-2016 Xavi Julian <xavier.julian@kaleidos.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# File: modules/common/history.coffee
###
taiga = @.taiga
trim = @.taiga.trim
bindOnce = @.taiga.bindOnce
debounce = @.taiga.debounce
module = angular.module("taigaCommon")
IGNORED_FIELDS = {
"userstories.userstory": [
"watchers", "kanban_order", "backlog_order", "sprint_order", "finish_date", "tribe_gig"
],
"tasks.task": [
"watchers", "us_order", "taskboard_order"
],
"issues.issue": [
"watchers"
]
}
#############################################################################
## History Directive (Main)
#############################################################################
class HistoryController extends taiga.Controller
@.$inject = ["$scope", "$tgRepo", "$tgResources"]
constructor: (@scope, @repo, @rs) ->
initialize: (type, objectId) ->
@.type = type
@.objectId = objectId
loadHistory: (type, objectId) ->
return @rs.history.get(type, objectId).then (history) =>
for historyResult in history
# If description was modified take only the description_html field
if historyResult.values_diff.description_diff?
historyResult.values_diff.description = historyResult.values_diff.description_diff
delete historyResult.values_diff.description_html
delete historyResult.values_diff.description_diff
# If block note was modified take only the blocked_note_html field
if historyResult.values_diff.blocked_note_diff?
historyResult.values_diff.blocked_note = historyResult.values_diff.blocked_note_diff
delete historyResult.values_diff.blocked_note_html
delete historyResult.values_diff.blocked_note_diff
for historyEntry in history
changeModel = historyEntry.key.split(":")[0]
if IGNORED_FIELDS[changeModel]?
historyEntry.values_diff = _.removeKeys(historyEntry.values_diff, IGNORED_FIELDS[changeModel])
@scope.history = _.filter(history, (item) -> Object.keys(item.values_diff).length > 0)
@scope.comments = _.filter(history, (item) -> item.comment != "")
deleteComment: (type, objectId, activityId) ->
return @rs.history.deleteComment(type, objectId, activityId).then => @.loadHistory(type, objectId)
undeleteComment: (type, objectId, activityId) ->
return @rs.history.undeleteComment(type, objectId, activityId).then => @.loadHistory(type, objectId)
HistoryDirective = ($log, $loading, $qqueue, $template, $confirm, $translate, $compile, $navUrls, $rootScope, checkPermissionsService) ->
templateChangeDiff = $template.get("common/history/history-change-diff.html", true)
templateChangePoints = $template.get("common/history/history-change-points.html", true)
templateChangeGeneric = $template.get("common/history/history-change-generic.html", true)
templateChangeAttachment = $template.get("common/history/history-change-attachment.html", true)
templateChangeList = $template.get("common/history/history-change-list.html", true)
templateDeletedComment = $template.get("common/history/history-deleted-comment.html", true)
templateActivity = $template.get("common/history/history-activity.html", true)
templateBaseEntries = $template.get("common/history/history-base-entries.html", true)
templateBase = $template.get("common/history/history-base.html", true)
link = ($scope, $el, $attrs, $ctrl) ->
# Bootstraping
type = $attrs.type
objectId = null
showAllComments = false
showAllActivity = false
getPrettyDateFormat = ->
return $translate.instant("ACTIVITY.DATETIME")
bindOnce $scope, $attrs.ngModel, (model) ->
type = $attrs.type
objectId = model.id
$ctrl.initialize(type, objectId)
$ctrl.loadHistory(type, objectId)
# Helpers
getHumanizedFieldName = (field) ->
humanizedFieldNames = {
subject : $translate.instant("ACTIVITY.FIELDS.SUBJECT")
name: $translate.instant("ACTIVITY.FIELDS.NAME")
description : $translate.instant("ACTIVITY.FIELDS.DESCRIPTION")
content: $translate.instant("ACTIVITY.FIELDS.CONTENT")
status: $translate.instant("ACTIVITY.FIELDS.STATUS")
is_closed : $translate.instant("ACTIVITY.FIELDS.IS_CLOSED")
finish_date : $translate.instant("ACTIVITY.FIELDS.FINISH_DATE")
type: $translate.instant("ACTIVITY.FIELDS.TYPE")
priority: $translate.instant("ACTIVITY.FIELDS.PRIORITY")
severity: $translate.instant("ACTIVITY.FIELDS.SEVERITY")
assigned_to : $translate.instant("ACTIVITY.FIELDS.ASSIGNED_TO")
watchers : $translate.instant("ACTIVITY.FIELDS.WATCHERS")
milestone : $translate.instant("ACTIVITY.FIELDS.MILESTONE")
user_story: $translate.instant("ACTIVITY.FIELDS.USER_STORY")
project: $translate.instant("ACTIVITY.FIELDS.PROJECT")
is_blocked: $translate.instant("ACTIVITY.FIELDS.IS_BLOCKED")
blocked_note: $translate.instant("ACTIVITY.FIELDS.BLOCKED_NOTE")
points: $translate.instant("ACTIVITY.FIELDS.POINTS")
client_requirement : $translate.instant("ACTIVITY.FIELDS.CLIENT_REQUIREMENT")
team_requirement : $translate.instant("ACTIVITY.FIELDS.TEAM_REQUIREMENT")
is_iocaine: $translate.instant("ACTIVITY.FIELDS.IS_IOCAINE")
tags: $translate.instant("ACTIVITY.FIELDS.TAGS")
attachments : $translate.instant("ACTIVITY.FIELDS.ATTACHMENTS")
is_deprecated: $translate.instant("ACTIVITY.FIELDS.IS_DEPRECATED")
blocked_note: $translate.instant("ACTIVITY.FIELDS.BLOCKED_NOTE")
is_blocked: $translate.instant("ACTIVITY.FIELDS.IS_BLOCKED")
order: $translate.instant("ACTIVITY.FIELDS.ORDER")
backlog_order: $translate.instant("ACTIVITY.FIELDS.BACKLOG_ORDER")
sprint_order: $translate.instant("ACTIVITY.FIELDS.SPRINT_ORDER")
kanban_order: $translate.instant("ACTIVITY.FIELDS.KANBAN_ORDER")
taskboard_order: $translate.instant("ACTIVITY.FIELDS.TASKBOARD_ORDER")
us_order: $translate.instant("ACTIVITY.FIELDS.US_ORDER")
}
return humanizedFieldNames[field] or field
countChanges = (comment) ->
return _.keys(comment.values_diff).length
formatChange = (change) ->
if _.isArray(change)
if change.length == 0
return $translate.instant("ACTIVITY.VALUES.EMPTY")
return change.join(", ")
if change == ""
return $translate.instant("ACTIVITY.VALUES.EMPTY")
if not change? or change == false
return $translate.instant("ACTIVITY.VALUES.NO")
if change == true
return $translate.instant("ACTIVITY.VALUES.YES")
return change
# Render into string (operations without mutability)
renderAttachmentEntry = (value) ->
attachments = _.map value, (changes, type) ->
if type == "new"
return _.map changes, (change) ->
return templateChangeDiff({
name: $translate.instant("ACTIVITY.NEW_ATTACHMENT"),
diff: change.filename
})
else if type == "deleted"
return _.map changes, (change) ->
return templateChangeDiff({
name: $translate.instant("ACTIVITY.DELETED_ATTACHMENT"),
diff: change.filename
})
else
return _.map changes, (change) ->
name = $translate.instant("ACTIVITY.UPDATED_ATTACHMENT", {filename: change.filename})
diff = _.map change.changes, (values, name) ->
return {
name: getHumanizedFieldName(name)
from: formatChange(values[0])
to: formatChange(values[1])
}
return templateChangeAttachment({name: name, diff: diff})
return _.flatten(attachments).join("\n")
renderCustomAttributesEntry = (value) ->
customAttributes = _.map value, (changes, type) ->
if type == "new"
return _.map changes, (change) ->
html = templateChangeGeneric({
name: change.name,
from: formatChange(""),
to: formatChange(change.value)
})
html = $compile(html)($scope)
return html[0].outerHTML
else if type == "deleted"
return _.map changes, (change) ->
return templateChangeDiff({
name: $translate.instant("ACTIVITY.DELETED_CUSTOM_ATTRIBUTE")
diff: change.name
})
else
return _.map changes, (change) ->
customAttrsChanges = _.map change.changes, (values) ->
return templateChangeGeneric({
name: change.name
from: formatChange(values[0])
to: formatChange(values[1])
})
return _.flatten(customAttrsChanges).join("\n")
return _.flatten(customAttributes).join("\n")
renderChangeEntry = (field, value) ->
if field == "description"
return templateChangeDiff({name: getHumanizedFieldName("description"), diff: value[1]})
else if field == "blocked_note"
return templateChangeDiff({name: getHumanizedFieldName("blocked_note"), diff: value[1]})
else if field == "points"
html = templateChangePoints({points: value})
html = $compile(html)($scope)
return html[0].outerHTML
else if field == "attachments"
return renderAttachmentEntry(value)
else if field == "custom_attributes"
return renderCustomAttributesEntry(value)
else if field in ["tags", "watchers"]
name = getHumanizedFieldName(field)
removed = _.difference(value[0], value[1])
added = _.difference(value[1], value[0])
html = templateChangeList({name:name, removed:removed, added: added})
html = $compile(html)($scope)
return html[0].outerHTML
else if field == "assigned_to"
name = getHumanizedFieldName(field)
from = formatChange(value[0] or $translate.instant("ACTIVITY.VALUES.UNASSIGNED"))
to = formatChange(value[1] or $translate.instant("ACTIVITY.VALUES.UNASSIGNED"))
return templateChangeGeneric({name:name, from:from, to: to})
else
name = getHumanizedFieldName(field)
from = formatChange(value[0])
to = formatChange(value[1])
return templateChangeGeneric({name:name, from:from, to: to})
renderChangeEntries = (change) ->
return _.map(change.values_diff, (value, field) -> renderChangeEntry(field, value))
renderChangesHelperText = (change) ->
size = countChanges(change)
return $translate.instant("ACTIVITY.SIZE_CHANGE", {size: size}, 'messageformat')
renderComment = (comment) ->
if (comment.delete_comment_date or comment.delete_comment_user?.name)
html = templateDeletedComment({
deleteCommentDate: moment(comment.delete_comment_date).format(getPrettyDateFormat()) if comment.delete_comment_date
deleteCommentUser: comment.delete_comment_user.name
deleteComment: comment.comment_html
activityId: comment.id
canRestoreComment: ($scope.user and
(comment.delete_comment_user.pk == $scope.user.id or
$scope.project.my_permissions.indexOf("modify_project") > -1))
})
html = $compile(html)($scope)
return html[0].outerHTML
html = templateActivity({
avatar: comment.user.photo
userFullName: comment.user.name
userProfileUrl: if comment.user.is_active then $navUrls.resolve("user-profile", {username: comment.user.username}) else ""
creationDate: moment(comment.created_at).format(getPrettyDateFormat())
comment: comment.comment_html
changesText: renderChangesHelperText(comment)
changes: renderChangeEntries(comment)
mode: "comment"
deleteCommentActionTitle: $translate.instant("COMMENTS.DELETE")
deleteCommentDate: moment(comment.delete_comment_date).format(getPrettyDateFormat()) if comment.delete_comment_date
deleteCommentUser: comment.delete_comment_user.name if comment.delete_comment_user?.name
activityId: comment.id
canDeleteComment: comment.user.pk == $scope.user?.id or $scope.project.my_permissions.indexOf("modify_project") > -1
})
html = $compile(html)($scope)
return html[0].outerHTML
renderChange = (change) ->
return templateActivity({
avatar: change.user.photo
userFullName: change.user.name
userProfileUrl: if change.user.is_active then $navUrls.resolve("user-profile", {username: change.user.username}) else ""
creationDate: moment(change.created_at).format(getPrettyDateFormat())
comment: change.comment_html
changes: renderChangeEntries(change)
changesText: ""
mode: "activity"
deleteCommentDate: moment(change.delete_comment_date).format(getPrettyDateFormat()) if change.delete_comment_date
deleteCommentUser: change.delete_comment_user.name if change.delete_comment_user?.name
activityId: change.id
})
renderHistory = (entries, totalEntries) ->
if entries.length == totalEntries
showMore = 0
else
showMore = totalEntries - entries.length
html = templateBaseEntries({entries: entries, showMore:showMore})
html = $compile(html)($scope)
return html
# Render into DOM (operations with dom mutability)
renderBase = ->
comments = $scope.comments or []
changes = $scope.history or []
historyVisible = !!changes.length
commentsVisible = (!!comments.length) || checkPermissionsService.check('modify_' + $attrs.type)
html = templateBase({
ngmodel: $attrs.ngModel,
type: $attrs.type,
mode: $attrs.mode,
historyVisible: historyVisible,
commentsVisible: commentsVisible
})
html = $compile(html)($scope)
$el.html(html)
rerender = ->
renderBase()
renderComments()
renderActivity()
renderComments = ->
comments = $scope.comments or []
totalComments = comments.length
if not showAllComments
comments = _.takeRight(comments, 4)
comments = _.map comments, (x) -> renderComment(x)
html = renderHistory(comments, totalComments)
$el.find(".comments-list").html(html)
renderActivity = ->
changes = $scope.history or []
totalChanges = changes.length
if not showAllActivity
changes = _.takeRight(changes, 4)
changes = _.map(changes, (x) -> renderChange(x))
html = renderHistory(changes, totalChanges)
$el.find(".changes-list").html(html)
save = $qqueue.bindAdd (target) =>
$scope.$broadcast("markdown-editor:submit")
$el.find(".comment-list").addClass("activeanimation")
currentLoading = $loading()
.target(target)
.start()
onSuccess = ->
$rootScope.$broadcast("comment:new")
$ctrl.loadHistory(type, objectId).finally ->
currentLoading.finish()
onError = ->
currentLoading.finish()
$confirm.notify("error")
model = $scope.$eval($attrs.ngModel)
$ctrl.repo.save(model).then(onSuccess, onError)
# Watchers
$scope.$watch("comments", rerender)
$scope.$watch("history", rerender)
$scope.$on("object:updated", -> $ctrl.loadHistory(type, objectId))
# Events
$el.on "click", ".add-comment .button-green", debounce 2000, (event) ->
event.preventDefault()
target = angular.element(event.currentTarget)
save(target)
$el.on "click", "a", (event) ->
target = angular.element(event.target)
href = target.attr('href')
if href && href.indexOf("#") == 0
event.preventDefault()
$('body').scrollTop($(href).offset().top)
$el.on "click", ".show-more", (event) ->
event.preventDefault()
target = angular.element(event.currentTarget)
if target.parent().is(".changes-list")
showAllActivity = not showAllActivity
renderActivity()
else
showAllComments = not showAllComments
renderComments()
$el.on "click", ".show-deleted-comment", (event) ->
event.preventDefault()
target = angular.element(event.currentTarget)
target.parents('.activity-single').find('.hide-deleted-comment').show()
target.parents('.activity-single').find('.show-deleted-comment').hide()
target.parents('.activity-single').find('.comment-body').show()
$el.on "click", ".hide-deleted-comment", (event) ->
event.preventDefault()
target = angular.element(event.currentTarget)
target.parents('.activity-single').find('.hide-deleted-comment').hide()
target.parents('.activity-single').find('.show-deleted-comment').show()
target.parents('.activity-single').find('.comment-body').hide()
$el.on "click", ".changes-title", (event) ->
event.preventDefault()
target = angular.element(event.currentTarget)
target.parent().find(".change-entry").toggleClass("active")
$el.on "focus", ".add-comment textarea", (event) ->
$(this).addClass('active')
$el.on "click", ".history-tabs a", (event) ->
target = angular.element(event.currentTarget)
$el.find(".history-tabs li").removeClass("active")
target.parent().addClass("active")
$el.find(".history section").addClass("hidden")
$el.find(".history section.#{target.data('section-class')}").removeClass("hidden")
$el.on "click", ".comment-delete", debounce 2000, (event) ->
event.preventDefault()
target = angular.element(event.currentTarget)
activityId = target.data('activity-id')
$ctrl.deleteComment(type, objectId, activityId)
$el.on "click", ".comment-restore", debounce 2000, (event) ->
event.preventDefault()
target = angular.element(event.currentTarget)
activityId = target.data('activity-id')
$ctrl.undeleteComment(type, objectId, activityId)
$scope.$on "$destroy", ->
$el.off()
renderBase()
return {
controller: HistoryController
restrict: "AE"
link: link
# require: ["ngModel", "tgHistory"]
}
module.directive("tgHistory", ["$log", "$tgLoading", "$tgQqueue", "$tgTemplate", "$tgConfirm", "$translate",
"$compile", "$tgNavUrls", "$rootScope", "tgCheckPermissionsService", HistoryDirective])

View File

@ -28,6 +28,7 @@ bindOnce = @.taiga.bindOnce
timeout = @.taiga.timeout timeout = @.taiga.timeout
debounce = @.taiga.debounce debounce = @.taiga.debounce
sizeFormat = @.taiga.sizeFormat sizeFormat = @.taiga.sizeFormat
trim = @.taiga.trim
############################################################################# #############################################################################
## Common Lightbox Services ## Common Lightbox Services
@ -35,9 +36,11 @@ sizeFormat = @.taiga.sizeFormat
# the lightboxContent hide/show doesn't have sense because is an IE hack # the lightboxContent hide/show doesn't have sense because is an IE hack
class LightboxService extends taiga.Service class LightboxService extends taiga.Service
constructor: (@animationFrame, @q) -> constructor: (@animationFrame, @q, @rootScope) ->
open: ($el, onClose) ->
@.onClose = onClose
open: ($el) ->
if _.isString($el) if _.isString($el)
$el = $($el) $el = $($el)
defered = @q.defer() defered = @q.defer()
@ -70,25 +73,29 @@ class LightboxService extends taiga.Service
return defered.promise return defered.promise
close: ($el) -> close: ($el) ->
if _.isString($el) return new Promise (resolve) =>
$el = $($el) if _.isString($el)
docEl = angular.element(document) $el = $($el)
docEl.off(".lightbox") docEl = angular.element(document)
docEl.off(".keyboard-navigation") # Hack: to fix problems in the WYSIWYG textareas when press ENTER docEl.off(".lightbox")
docEl.off(".keyboard-navigation") # Hack: to fix problems in the WYSIWYG textareas when press ENTER
@animationFrame.add -> @animationFrame.add =>
$el.addClass('close') $el.addClass('close')
$el.one "transitionend", => $el.one "transitionend", =>
$el.removeAttr('style') $el.removeAttr('style')
$el.removeClass("open").removeClass('close') $el.removeClass("open").removeClass('close')
if @.onClose
@rootScope.$apply(@.onClose)
resolve()
if $el.hasClass("remove-on-close") if $el.hasClass("remove-on-close")
scope = $el.data("scope") scope = $el.data("scope")
scope.$destroy() if scope scope.$destroy() if scope
$el.remove() $el.remove()
closeAll: -> closeAll: ->
docEl = angular.element(document) docEl = angular.element(document)
@ -96,7 +103,7 @@ class LightboxService extends taiga.Service
@.close($(lightboxEl)) @.close($(lightboxEl))
module.service("lightboxService", ["animationFrame", "$q", LightboxService]) module.service("lightboxService", ["animationFrame", "$q", "$rootScope", LightboxService])
class LightboxKeyboardNavigationService extends taiga.Service class LightboxKeyboardNavigationService extends taiga.Service
@ -292,7 +299,44 @@ CreateEditUserstoryDirective = ($repo, $model, $rs, $rootScope, lightboxService,
attachmentsToAdd = attachmentsToAdd.push(attachment) attachmentsToAdd = attachmentsToAdd.push(attachment)
$scope.deleteAttachment = (attachment) -> $scope.deleteAttachment = (attachment) ->
attachmentsToDelete = attachmentsToDelete.push(attachment) if attachment.get("id")
attachmentsToDelete = attachmentsToDelete.push(attachment)
$scope.addTag = (tag, color) ->
value = trim(tag.toLowerCase())
tags = $scope.project.tags
projectTags = $scope.project.tags_colors
tags = [] if not tags?
projectTags = {} if not projectTags?
if value not in tags
tags.push(value)
projectTags[tag] = color || null
$scope.project.tags = tags
itemtags = _.clone($scope.us.tags)
inserted = _.find itemtags, (it) -> it[0] == value
if !inserted
itemtags.push([tag , color])
$scope.us.tags = itemtags
$scope.deleteTag = (tag) ->
value = trim(tag[0].toLowerCase())
tags = $scope.project.tags
itemtags = _.clone($scope.us.tags)
_.remove itemtags, (tag) -> tag[0] == value
$scope.us.tags = itemtags
_.pull($scope.us.tags, value)
$scope.$on "usform:new", (ctx, projectId, status, statusList) -> $scope.$on "usform:new", (ctx, projectId, status, statusList) ->
form.reset() if form form.reset() if form
@ -320,7 +364,10 @@ CreateEditUserstoryDirective = ($repo, $model, $rs, $rootScope, lightboxService,
$el.find("label.team-requirement").removeClass("selected") $el.find("label.team-requirement").removeClass("selected")
$el.find("label.client-requirement").removeClass("selected") $el.find("label.client-requirement").removeClass("selected")
lightboxService.open($el) $scope.createEditUsOpen = true
lightboxService.open $el, () ->
$scope.createEditUsOpen = false
$scope.$on "usform:edit", (ctx, us, attachments) -> $scope.$on "usform:edit", (ctx, us, attachments) ->
form.reset() if form form.reset() if form
@ -353,7 +400,10 @@ CreateEditUserstoryDirective = ($repo, $model, $rs, $rootScope, lightboxService,
else else
$el.find("label.client-requirement").removeClass("selected") $el.find("label.client-requirement").removeClass("selected")
lightboxService.open($el) $scope.createEditUsOpen = true
lightboxService.open $el, () ->
$scope.createEditUsOpen = false
createAttachments = (obj) -> createAttachments = (obj) ->
promises = _.map attachmentsToAdd.toJS(), (attachment) -> promises = _.map attachmentsToAdd.toJS(), (attachment) ->
@ -378,22 +428,28 @@ CreateEditUserstoryDirective = ($repo, $model, $rs, $rootScope, lightboxService,
.target(submitButton) .target(submitButton)
.start() .start()
params = {
include_attachments: true,
include_tasks: true
}
if $scope.isNew if $scope.isNew
promise = $repo.create("userstories", $scope.us) promise = $repo.create("userstories", $scope.us)
broadcastEvent = "usform:new:success" broadcastEvent = "usform:new:success"
else else
promise = $repo.save($scope.us) promise = $repo.save($scope.us, true)
broadcastEvent = "usform:edit:success" broadcastEvent = "usform:edit:success"
promise.then (data) -> promise.then (data) ->
deleteAttachments(data).then () => createAttachments(data) deleteAttachments(data)
.then () => createAttachments(data)
.then () =>
currentLoading.finish()
lightboxService.close($el)
return data $rs.userstories.getByRef(data.project, data.ref, params).then (us) ->
$rootScope.$broadcast(broadcastEvent, us)
promise.then (data) ->
currentLoading.finish()
lightboxService.close($el)
$rootScope.$broadcast(broadcastEvent, data)
promise.then null, (data) -> promise.then null, (data) ->
currentLoading.finish() currentLoading.finish()
@ -407,8 +463,10 @@ CreateEditUserstoryDirective = ($repo, $model, $rs, $rootScope, lightboxService,
$el.on "click", ".close", (event) -> $el.on "click", ".close", (event) ->
event.preventDefault() event.preventDefault()
$scope.$apply -> $scope.$apply ->
$scope.us.revert() $scope.us.revert()
lightboxService.close($el) lightboxService.close($el)
$el.keydown (event) -> $el.keydown (event) ->
@ -433,7 +491,7 @@ module.directive("tgLbCreateEditUserstory", [
"$translate", "$translate",
"$tgConfirm", "$tgConfirm",
"$q", "$q",
"tgAttachmentsService", "tgAttachmentsService"
CreateEditUserstoryDirective CreateEditUserstoryDirective
]) ])
@ -442,7 +500,7 @@ module.directive("tgLbCreateEditUserstory", [
## Creare Bulk Userstories Lightbox Directive ## Creare Bulk Userstories Lightbox Directive
############################################################################# #############################################################################
CreateBulkUserstoriesDirective = ($repo, $rs, $rootscope, lightboxService, $loading) -> CreateBulkUserstoriesDirective = ($repo, $rs, $rootscope, lightboxService, $loading, $model) ->
link = ($scope, $el, attrs) -> link = ($scope, $el, attrs) ->
form = null form = null
@ -469,6 +527,7 @@ CreateBulkUserstoriesDirective = ($repo, $rs, $rootscope, lightboxService, $load
promise = $rs.userstories.bulkCreate($scope.new.projectId, $scope.new.statusId, $scope.new.bulk) promise = $rs.userstories.bulkCreate($scope.new.projectId, $scope.new.statusId, $scope.new.bulk)
promise.then (result) -> promise.then (result) ->
result = _.map(result.data, (x) => $model.make_model('userstories', x))
currentLoading.finish() currentLoading.finish()
$rootscope.$broadcast("usform:bulk:success", result) $rootscope.$broadcast("usform:bulk:success", result)
lightboxService.close($el) lightboxService.close($el)
@ -494,6 +553,7 @@ module.directive("tgLbCreateBulkUserstories", [
"$rootScope", "$rootScope",
"lightboxService", "lightboxService",
"$tgLoading", "$tgLoading",
"$tgModel",
CreateBulkUserstoriesDirective CreateBulkUserstoriesDirective
]) ])
@ -502,7 +562,7 @@ module.directive("tgLbCreateBulkUserstories", [
## AssignedTo Lightbox Directive ## AssignedTo Lightbox Directive
############################################################################# #############################################################################
AssignedToLightboxDirective = (lightboxService, lightboxKeyboardNavigationService, $template, $compile) -> AssignedToLightboxDirective = (lightboxService, lightboxKeyboardNavigationService, $template, $compile, avatarService) ->
link = ($scope, $el, $attrs) -> link = ($scope, $el, $attrs) ->
selectedUser = null selectedUser = null
selectedItem = null selectedItem = null
@ -527,12 +587,21 @@ AssignedToLightboxDirective = (lightboxService, lightboxKeyboardNavigationServic
render = (selected, text) -> render = (selected, text) ->
users = _.clone($scope.activeUsers, true) users = _.clone($scope.activeUsers, true)
users = _.reject(users, {"id": selected.id}) if selected? users = _.reject(users, {"id": selected.id}) if selected?
users = _.sortBy(users, (o) -> if o.id is $scope.user.id then 0 else o.id)
users = _.filter(users, _.partial(filterUsers, text)) if text? users = _.filter(users, _.partial(filterUsers, text)) if text?
visibleUsers = _.slice(users, 0, 5)
visibleUsers = _.map visibleUsers, (user) ->
user.avatar = avatarService.getAvatar(user)
if selected
selected.avatar = avatarService.getAvatar(selected) if selected
ctx = { ctx = {
selected: selected selected: selected
users: _.slice(users, 0, 5) users: _.slice(users, 0, 5)
showMore: users.length > 5 showMore: visibleUsers
} }
html = usersTemplate(ctx) html = usersTemplate(ctx)
@ -596,14 +665,14 @@ AssignedToLightboxDirective = (lightboxService, lightboxKeyboardNavigationServic
} }
module.directive("tgLbAssignedto", ["lightboxService", "lightboxKeyboardNavigationService", "$tgTemplate", "$compile", AssignedToLightboxDirective]) module.directive("tgLbAssignedto", ["lightboxService", "lightboxKeyboardNavigationService", "$tgTemplate", "$compile", "tgAvatarService", AssignedToLightboxDirective])
############################################################################# #############################################################################
## Watchers Lightbox directive ## Watchers Lightbox directive
############################################################################# #############################################################################
WatchersLightboxDirective = ($repo, lightboxService, lightboxKeyboardNavigationService, $template, $compile) -> WatchersLightboxDirective = ($repo, lightboxService, lightboxKeyboardNavigationService, $template, $compile, avatarService) ->
link = ($scope, $el, $attrs) -> link = ($scope, $el, $attrs) ->
selectedItem = null selectedItem = null
usersTemplate = $template.get("common/lightbox/lightbox-assigned-to-users.html", true) usersTemplate = $template.get("common/lightbox/lightbox-assigned-to-users.html", true)
@ -625,9 +694,16 @@ WatchersLightboxDirective = ($repo, lightboxService, lightboxKeyboardNavigationS
# Render the specific list of users. # Render the specific list of users.
render = (users) -> render = (users) ->
visibleUsers = _.slice(users, 0, 5)
visibleUsers = _.map visibleUsers, (user) ->
user.avatar = avatarService.getAvatar(user)
return user
ctx = { ctx = {
selected: false selected: false
users: _.slice(users, 0, 5) users: visibleUsers
showMore: users.length > 5 showMore: users.length > 5
} }
@ -683,25 +759,9 @@ WatchersLightboxDirective = ($repo, lightboxService, lightboxKeyboardNavigationS
link:link link:link
} }
module.directive("tgLbWatchers", ["$tgRepo", "lightboxService", "lightboxKeyboardNavigationService", "$tgTemplate", "$compile", WatchersLightboxDirective]) module.directive("tgLbWatchers", ["$tgRepo", "lightboxService", "lightboxKeyboardNavigationService", "$tgTemplate", "$compile", "tgAvatarService", WatchersLightboxDirective])
#############################################################################
## Attachment Preview Lighbox
#############################################################################
AttachmentPreviewLightboxDirective = (lightboxService, $template, $compile) ->
link = ($scope, $el, attrs) ->
lightboxService.open($el)
return {
templateUrl: 'common/lightbox/lightbox-attachment-preview.html',
link: link,
scope: true
}
module.directive("tgLbAttachmentPreview", ["lightboxService", "$tgTemplate", "$compile", AttachmentPreviewLightboxDirective])
LightboxLeaveProjectWarningDirective = (lightboxService, $template, $compile) -> LightboxLeaveProjectWarningDirective = (lightboxService, $template, $compile) ->
link = ($scope, $el, attrs) -> link = ($scope, $el, attrs) ->
lightboxService.open($el) lightboxService.open($el)

View File

@ -59,6 +59,7 @@ TgLoadingService = ($compile) ->
start: -> start: ->
target = service.settings.target target = service.settings.target
service.settings.classes.map (className) -> target.removeClass(className) service.settings.classes.map (className) -> target.removeClass(className)
if not target.hasClass('loading') && !service.settings.template if not target.hasClass('loading') && !service.settings.template
@ -109,6 +110,7 @@ LoadingDirective = ($loading) ->
template = $el.html() template = $el.html()
$scope.$watch attr.tgLoading, (showLoading) => $scope.$watch attr.tgLoading, (showLoading) =>
if showLoading if showLoading
currentLoading = $loading() currentLoading = $loading()
.target($el) .target($el)
@ -120,6 +122,7 @@ LoadingDirective = ($loading) ->
currentLoading.finish() currentLoading.finish()
return { return {
priority: 99999,
link:link link:link
} }

View File

@ -26,6 +26,7 @@ taiga = @.taiga
trim = @.taiga.trim trim = @.taiga.trim
bindOnce = @.taiga.bindOnce bindOnce = @.taiga.bindOnce
module = angular.module("taigaCommon") module = angular.module("taigaCommon")
# Directive that parses/format tags inputfield. # Directive that parses/format tags inputfield.
@ -61,28 +62,38 @@ ColorizeTagsDirective = ->
templates = { templates = {
backlog: _.template(""" backlog: _.template("""
<% _.each(tags, function(tag) { %> <% _.each(tags, function(tag) { %>
<span class="tag" style="border-left: 5px solid <%- tag.color %>"><%- tag.name %></span> <span class="tag"
<% if (tag[1] !== null) { %>
style="border-left: 5px solid <%- tag[1] %>"
<% } %>
title="<%- tag[0] %>"><%- tag[0] %></span>
<% }) %> <% }) %>
""") """)
kanban: _.template(""" kanban: _.template("""
<% _.each(tags, function(tag) { %> <% _.each(tags, function(tag) { %>
<a class="kanban-tag" href="" style="border-color: <%- tag.color %>" title="<%- tag.name %>" /> <a class="kanban-tag"
href=""
<% if (tag[1] !== null) { %>
style="border-color: <%- tag[1] %>"
<% } %>
title="<%- tag[0] %>" />
<% }) %> <% }) %>
""") """)
taskboard: _.template(""" taskboard: _.template("""
<% _.each(tags, function(tag) { %> <% _.each(tags, function(tag) { %>
<a class="taskboard-tag" href="" style="border-color: <%- tag.color %>" title="<%- tag.name %>" /> <a class="taskboard-tag"
href=""
<% if (tag[1] !== null) { %>
style="border-color: <%- tag[1] %>"
<% } %>
title="<%- tag[0] %>" />
<% }) %> <% }) %>
""") """)
} }
link = ($scope, $el, $attrs, $ctrl) -> link = ($scope, $el, $attrs, $ctrl) ->
render = (srcTags) -> render = (tags) ->
template = templates[$attrs.tgColorizeTagsType] template = templates[$attrs.tgColorizeTagsType]
srcTags.sort()
tags = _.map srcTags, (tag) ->
color = $scope.project.tags_colors[tag]
return {name: tag, color: color}
html = template({tags: tags}) html = template({tags: tags})
$el.html(html) $el.html(html)
@ -111,15 +122,18 @@ LbTagLineDirective = ($rs, $template, $compile) ->
autocomplete = null autocomplete = null
link = ($scope, $el, $attrs, $model) -> link = ($scope, $el, $attrs, $model) ->
## Render withoutColors = _.has($attrs, "withoutColors")
renderTags = (tags, tagsColors) ->
ctx = {
tags: _.map(tags, (t) -> {name: t, color: tagsColors[t]})
}
_.map ctx.tags, (tag) => ## Render
if tag.color renderTags = (tags, tagsColors = []) ->
tag.style = "border-left: 5px solid #{tag.color}" color = if not withoutColors then tagsColors[t] else null
ctx = {
tags: _.map(tags, (t) -> {
name: t,
style: if color then "border-left: 5px solid #{color}" else ""
})
}
html = $compile(templateTags(ctx))($scope) html = $compile(templateTags(ctx))($scope)
$el.find(".tags-container").html(html) $el.find(".tags-container").html(html)
@ -196,7 +210,7 @@ LbTagLineDirective = ($rs, $template, $compile) ->
autocomplete = new Awesomplete(input[0], { autocomplete = new Awesomplete(input[0], {
list: _.keys(project.tags_colors) list: _.keys(project.tags_colors)
}); })
input.on "awesomplete-selectcomplete", () -> input.on "awesomplete-selectcomplete", () ->
addValue(input.val()) addValue(input.val())
@ -216,189 +230,3 @@ LbTagLineDirective = ($rs, $template, $compile) ->
} }
module.directive("tgLbTagLine", ["$tgResources", "$tgTemplate", "$compile", LbTagLineDirective]) module.directive("tgLbTagLine", ["$tgResources", "$tgTemplate", "$compile", LbTagLineDirective])
#############################################################################
## TagLine Directive (for detail pages)
#############################################################################
TagLineDirective = ($rootScope, $repo, $rs, $confirm, $modelTransform, $template, $compile) ->
ENTER_KEY = 13
ESC_KEY = 27
COMMA_KEY = 188
templateTags = $template.get("common/tag/tags-line-tags.html", true)
link = ($scope, $el, $attrs, $model) ->
autocomplete = null
isEditable = ->
if $attrs.requiredPerm?
return $scope.project.my_permissions.indexOf($attrs.requiredPerm) != -1
return true
## Render
renderTags = (tags, tagsColors) ->
ctx = {
tags: _.map(tags, (t) -> {name: t, color: tagsColors[t]})
isEditable: isEditable()
}
html = $compile(templateTags(ctx))($scope)
$el.find("div.tags-container").html(html)
renderInReadModeOnly = ->
$el.find(".add-tag").remove()
$el.find("input").remove()
$el.find(".save").remove()
showAddTagButton = -> $el.find(".add-tag").removeClass("hidden")
hideAddTagButton = -> $el.find(".add-tag").addClass("hidden")
showAddTagButtonText = -> $el.find(".add-tag-text").removeClass("hidden")
hideAddTagButtonText = -> $el.find(".add-tag-text").addClass("hidden")
showSaveButton = -> $el.find(".save").removeClass("hidden")
hideSaveButton = -> $el.find(".save").addClass("hidden")
showInput = -> $el.find("input").removeClass("hidden").focus()
hideInput = -> $el.find("input").addClass("hidden").blur()
resetInput = ->
$el.find("input").val("")
autocomplete.close()
## Aux methods
addValue = (value) ->
value = trim(value.toLowerCase())
return if value.length == 0
transform = $modelTransform.save (item) ->
if not item.tags
item.tags = []
tags = _.clone(item.tags)
tags.push(value) if value not in tags
item.tags = tags
return item
onSuccess = ->
$rootScope.$broadcast("object:updated")
onError = ->
$confirm.notify("error")
hideSaveButton()
return transform.then(onSuccess, onError)
deleteValue = (value) ->
value = trim(value.toLowerCase())
return if value.length == 0
transform = $modelTransform.save (item) ->
tags = _.clone(item.tags, false)
item.tags = _.pull(tags, value)
return item
onSuccess = ->
$rootScope.$broadcast("object:updated")
onError = ->
$confirm.notify("error")
return transform.then(onSuccess, onError)
saveInputTag = () ->
value = $el.find("input").val()
addValue(value)
resetInput()
## Events
$el.on "keypress", "input", (event) ->
target = angular.element(event.currentTarget)
if event.keyCode == ENTER_KEY
saveInputTag()
else if String.fromCharCode(event.keyCode) == ','
event.preventDefault()
saveInputTag()
else
if target.val().length
showSaveButton()
else
hideSaveButton()
$el.on "keyup", "input", (event) ->
if event.keyCode == ESC_KEY
resetInput()
hideInput()
hideSaveButton()
showAddTagButton()
$el.on "click", ".save", (event) ->
event.preventDefault()
saveInputTag()
$el.on "click", ".add-tag", (event) ->
event.preventDefault()
hideAddTagButton()
showInput()
$el.on "click", ".remove-tag", (event) ->
event.preventDefault()
target = angular.element(event.currentTarget)
value = target.siblings(".tag-name").text()
deleteValue(value)
bindOnce $scope, "project.tags_colors", (tags_colors) ->
if not isEditable()
renderInReadModeOnly()
return
showAddTagButton()
input = $el.find("input")
autocomplete = new Awesomplete(input[0], {
list: _.keys(tags_colors)
});
input.on "awesomplete-selectcomplete", () ->
addValue(input.val())
input.val("")
$scope.$watchCollection () ->
return $model.$modelValue?.tags
, () ->
model = $model.$modelValue
return if not model
if model.tags?.length
hideAddTagButtonText()
else
showAddTagButtonText()
tagsColors = $scope.project?.tags_colors or []
renderTags(model.tags, tagsColors)
$scope.$on "$destroy", ->
$el.off()
return {
link:link,
require:"ngModel"
templateUrl: "common/tag/tag-line.html"
}
module.directive("tgTagLine", ["$rootScope", "$tgRepo", "$tgResources", "$tgConfirm", "$tgQueueModelTransformation",
"$tgTemplate", "$compile", TagLineDirective])

View File

@ -83,7 +83,7 @@ MarkitupDirective = ($rootscope, $rs, $selectedText, $template, $compile, $trans
markdownDomNode = element.parents(".markdown") markdownDomNode = element.parents(".markdown")
markItUpDomNode = element.parents(".markItUp") markItUpDomNode = element.parents(".markItUp")
$rs.mdrender.render($scope.projectId, $model.$modelValue).then (data) -> $rs.mdrender.render($scope.projectId || $scope.vm.projectId, $model.$modelValue).then (data) ->
html = previewTemplate({data: data.data}) html = previewTemplate({data: data.data})
html = $compile(html)($scope) html = $compile(html)($scope)
@ -374,7 +374,7 @@ MarkitupDirective = ($rootscope, $rs, $selectedText, $template, $compile, $trans
search: (term, callback) -> search: (term, callback) ->
term = taiga.slugify(term) term = taiga.slugify(term)
searchTypes = ['issues', 'tasks', 'userstories'] searchTypes = ['issues', 'tasks', 'userstories', 'epics']
searchProps = ['ref', 'subject'] searchProps = ['ref', 'subject']
filter = (item) => filter = (item) =>
@ -384,8 +384,7 @@ MarkitupDirective = ($rootscope, $rs, $selectedText, $template, $compile, $trans
return false return false
cancelablePromise.abort() if cancelablePromise cancelablePromise.abort() if cancelablePromise
cancelablePromise = $rs.search.do($scope.projectId || $scope.vm.projectId, term)
cancelablePromise = $rs.search.do($scope.projectId, term)
cancelablePromise.then (res) => cancelablePromise.then (res) =>
# ignore wikipages if they're the only results. can't exclude them in search # ignore wikipages if they're the only results. can't exclude them in search
@ -441,7 +440,7 @@ MarkitupDirective = ($rootscope, $rs, $selectedText, $template, $compile, $trans
search: (term, callback) -> search: (term, callback) ->
term = taiga.slugify(term) term = taiga.slugify(term)
$rs.search.do($scope.projectId, term).then (res) => $rs.search.do($scope.projectId || $scope.vm.projectId, term).then (res) =>
if res.count < 1 if res.count < 1
callback([]) callback([])

View File

@ -110,4 +110,201 @@ class FiltersMixin
location = if load then @location else @location.noreload(@scope) location = if load then @location else @location.noreload(@scope)
location.search(name, value) location.search(name, value)
applyStoredFilters: (projectSlug, key) ->
if _.isEmpty(@location.search())
filters = @.getFilters(projectSlug, key)
if Object.keys(filters).length
@location.search(filters)
@location.replace()
return true
return false
storeFilters: (projectSlug, params, filtersHashSuffix) ->
ns = "#{projectSlug}:#{filtersHashSuffix}"
hash = taiga.generateHash([projectSlug, ns])
@storage.set(hash, params)
getFilters: (projectSlug, filtersHashSuffix) ->
ns = "#{projectSlug}:#{filtersHashSuffix}"
hash = taiga.generateHash([projectSlug, ns])
return @storage.get(hash) or {}
formatSelectedFilters: (type, list, urlIds) ->
selectedIds = urlIds.split(',')
selectedFilters = _.filter list, (it) ->
selectedIds.indexOf(_.toString(it.id)) != -1
return _.map selectedFilters, (it) ->
return {
id: it.id
key: type + ":" + it.id
dataType: type,
name: it.name
color: it.color
}
taiga.FiltersMixin = FiltersMixin taiga.FiltersMixin = FiltersMixin
#############################################################################
## Us Filters Mixin
#############################################################################
class UsFiltersMixin
changeQ: (q) ->
@.replaceFilter("q", q)
@.filtersReloadContent()
@.generateFilters()
removeFilter: (filter) ->
@.unselectFilter(filter.dataType, filter.id)
@.filtersReloadContent()
@.generateFilters()
addFilter: (newFilter) ->
@.selectFilter(newFilter.category.dataType, newFilter.filter.id)
@.filtersReloadContent()
@.generateFilters()
selectCustomFilter: (customFilter) ->
@.replaceAllFilters(customFilter.filter)
@.filtersReloadContent()
@.generateFilters()
saveCustomFilter: (name) ->
filters = {}
urlfilters = @location.search()
filters.tags = urlfilters.tags
filters.status = urlfilters.status
filters.assigned_to = urlfilters.assigned_to
filters.owner = urlfilters.owner
@filterRemoteStorageService.getFilters(@scope.projectId, @.storeCustomFiltersName).then (userFilters) =>
userFilters[name] = filters
@filterRemoteStorageService.storeFilters(@scope.projectId, userFilters, @.storeCustomFiltersName).then(@.generateFilters)
removeCustomFilter: (customFilter) ->
@filterRemoteStorageService.getFilters(@scope.projectId, @.storeCustomFiltersName).then (userFilters) =>
delete userFilters[customFilter.id]
@filterRemoteStorageService.storeFilters(@scope.projectId, userFilters, @.storeCustomFiltersName).then(@.generateFilters)
@.generateFilters()
generateFilters: ->
@.storeFilters(@params.pslug, @location.search(), @.storeFiltersName)
urlfilters = @location.search()
loadFilters = {}
loadFilters.project = @scope.projectId
loadFilters.tags = urlfilters.tags
loadFilters.status = urlfilters.status
loadFilters.assigned_to = urlfilters.assigned_to
loadFilters.owner = urlfilters.owner
loadFilters.epic = urlfilters.epic
loadFilters.q = urlfilters.q
return @q.all([
@rs.userstories.filtersData(loadFilters),
@filterRemoteStorageService.getFilters(@scope.projectId, @.storeCustomFiltersName)
]).then (result) =>
data = result[0]
customFiltersRaw = result[1]
statuses = _.map data.statuses, (it) ->
it.id = it.id.toString()
return it
tags = _.map data.tags, (it) ->
it.id = it.name
return it
tagsWithAtLeastOneElement = _.filter tags, (tag) ->
return tag.count > 0
assignedTo = _.map data.assigned_to, (it) ->
if it.id
it.id = it.id.toString()
else
it.id = "null"
it.name = it.full_name || "Unassigned"
return it
owner = _.map data.owners, (it) ->
it.id = it.id.toString()
it.name = it.full_name
return it
epic = _.map data.epics, (it) ->
if it.id
it.id = it.id.toString()
it.name = "##{it.ref} #{it.subject}"
else
it.id = "null"
it.name = "Not in an epic"
return it
@.selectedFilters = []
if loadFilters.status
selected = @.formatSelectedFilters("status", statuses, loadFilters.status)
@.selectedFilters = @.selectedFilters.concat(selected)
if loadFilters.tags
selected = @.formatSelectedFilters("tags", tags, loadFilters.tags)
@.selectedFilters = @.selectedFilters.concat(selected)
if loadFilters.assigned_to
selected = @.formatSelectedFilters("assigned_to", assignedTo, loadFilters.assigned_to)
@.selectedFilters = @.selectedFilters.concat(selected)
if loadFilters.owner
selected = @.formatSelectedFilters("owner", owner, loadFilters.owner)
@.selectedFilters = @.selectedFilters.concat(selected)
if loadFilters.epic
selected = @.formatSelectedFilters("epic", epic, loadFilters.epic)
@.selectedFilters = @.selectedFilters.concat(selected)
@.filterQ = loadFilters.q
@.filters = [
{
title: @translate.instant("COMMON.FILTERS.CATEGORIES.STATUS"),
dataType: "status",
content: statuses
},
{
title: @translate.instant("COMMON.FILTERS.CATEGORIES.TAGS"),
dataType: "tags",
content: tags,
hideEmpty: true,
totalTaggedElements: tagsWithAtLeastOneElement.length
},
{
title: @translate.instant("COMMON.FILTERS.CATEGORIES.ASSIGNED_TO"),
dataType: "assigned_to",
content: assignedTo
},
{
title: @translate.instant("COMMON.FILTERS.CATEGORIES.CREATED_BY"),
dataType: "owner",
content: owner
},
{
title: @translate.instant("COMMON.FILTERS.CATEGORIES.EPIC"),
dataType: "epic",
content: epic
}
]
@.customFilters = []
_.forOwn customFiltersRaw, (value, key) =>
@.customFilters.push({id: key, name: key, filter: value})
taiga.UsFiltersMixin = UsFiltersMixin

View File

@ -0,0 +1,25 @@
###
# Copyright (C) 2014-2016 Andrey Antukh <niwi@niwi.nz>
# Copyright (C) 2014-2016 Jesús Espino Garcia <jespinog@gmail.com>
# Copyright (C) 2014-2016 David Barragán Merino <bameda@dbarragan.com>
# Copyright (C) 2014-2016 Alejandro Alonso <alejandro.alonso@kaleidos.net>
# Copyright (C) 2014-2016 Juan Francisco Alcántara <juanfran.alcantara@kaleidos.net>
# Copyright (C) 2014-2016 Xavi Julian <xavier.julian@kaleidos.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# File: modules/epics.coffee
###
module = angular.module("taigaEpics", [])

View File

@ -0,0 +1,337 @@
###
# Copyright (C) 2014-2016 Andrey Antukh <niwi@niwi.nz>
# Copyright (C) 2014-2016 Jesús Espino Garcia <jespinog@gmail.com>
# Copyright (C) 2014-2016 David Barragán Merino <bameda@dbarragan.com>
# Copyright (C) 2014-2016 Alejandro Alonso <alejandro.alonso@kaleidos.net>
# Copyright (C) 2014-2016 Juan Francisco Alcántara <juanfran.alcantara@kaleidos.net>
# Copyright (C) 2014-2016 Xavi Julian <xavier.julian@kaleidos.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# File: modules/epics/detail.coffee
###
taiga = @.taiga
mixOf = @.taiga.mixOf
toString = @.taiga.toString
joinStr = @.taiga.joinStr
groupBy = @.taiga.groupBy
bindOnce = @.taiga.bindOnce
bindMethods = @.taiga.bindMethods
module = angular.module("taigaEpics")
#############################################################################
## Epic Detail Controller
#############################################################################
class EpicDetailController extends mixOf(taiga.Controller, taiga.PageMixin)
@.$inject = [
"$scope",
"$rootScope",
"$tgRepo",
"$tgConfirm",
"$tgResources",
"tgResources"
"$routeParams",
"$q",
"$tgLocation",
"$log",
"tgAppMetaService",
"$tgAnalytics",
"$tgNavUrls",
"$translate",
"$tgQueueModelTransformation",
"tgErrorHandlingService"
]
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @rs2, @params, @q, @location,
@log, @appMetaService, @analytics, @navUrls, @translate, @modelTransform, @errorHandlingService) ->
bindMethods(@)
@scope.epicRef = @params.epicref
@scope.sectionName = @translate.instant("EPIC.SECTION_NAME")
@.initializeEventHandlers()
promise = @.loadInitialData()
# On Success
promise.then =>
@._setMeta()
@.initializeOnDeleteGoToUrl()
# On Error
promise.then null, @.onInitialDataError.bind(@)
_setMeta: ->
title = @translate.instant("EPIC.PAGE_TITLE", {
epicRef: "##{@scope.epic.ref}"
epicSubject: @scope.epic.subject
projectName: @scope.project.name
})
description = @translate.instant("EPIC.PAGE_DESCRIPTION", {
epicStatus: @scope.statusById[@scope.epic.status]?.name or "--"
epicDescription: angular.element(@scope.epic.description_html or "").text()
})
@appMetaService.setAll(title, description)
initializeEventHandlers: ->
@scope.$on "attachment:create", =>
@analytics.trackEvent("attachment", "create", "create attachment on epic", 1)
@scope.$on "comment:new", =>
@.loadEpic()
@scope.$on "custom-attributes-values:edit", =>
@rootscope.$broadcast("object:updated")
initializeOnDeleteGoToUrl: ->
ctx = {project: @scope.project.slug}
@scope.onDeleteGoToUrl = @navUrls.resolve("project-epics", ctx)
loadProject: ->
return @rs.projects.getBySlug(@params.pslug).then (project) =>
@scope.projectId = project.id
@scope.project = project
@scope.immutableProject = Immutable.fromJS(project._attrs)
@scope.$emit('project:loaded', project)
@scope.statusList = project.epic_statuses
@scope.statusById = groupBy(project.epic_statuses, (x) -> x.id)
return project
loadEpic: ->
return @rs.epics.getByRef(@scope.projectId, @params.epicref).then (epic) =>
@scope.epic = epic
@scope.immutableEpic = Immutable.fromJS(epic._attrs)
@scope.epicId = epic.id
@scope.commentModel = epic
@modelTransform.setObject(@scope, 'epic')
if @scope.epic.neighbors.previous?.ref?
ctx = {
project: @scope.project.slug
ref: @scope.epic.neighbors.previous.ref
}
@scope.previousUrl = @navUrls.resolve("project-epics-detail", ctx)
if @scope.epic.neighbors.next?.ref?
ctx = {
project: @scope.project.slug
ref: @scope.epic.neighbors.next.ref
}
@scope.nextUrl = @navUrls.resolve("project-epics-detail", ctx)
loadUserstories: ->
return @rs2.userstories.listInEpic(@scope.epicId).then (data) =>
@scope.userstories = data
loadInitialData: ->
promise = @.loadProject()
return promise.then (project) =>
@.fillUsersAndRoles(project.members, project.roles)
@.loadEpic().then(=> @.loadUserstories())
###
# Note: This methods (onUpvote() and onDownvote()) are related to tg-vote-button.
# See app/modules/components/vote-button for more info
###
onUpvote: ->
onSuccess = =>
@.loadEpic()
@rootscope.$broadcast("object:updated")
onError = =>
@confirm.notify("error")
return @rs.epics.upvote(@scope.epicId).then(onSuccess, onError)
onDownvote: ->
onSuccess = =>
@.loadEpic()
@rootscope.$broadcast("object:updated")
onError = =>
@confirm.notify("error")
return @rs.epics.downvote(@scope.epicId).then(onSuccess, onError)
###
# Note: This methods (onWatch() and onUnwatch()) are related to tg-watch-button.
# See app/modules/components/watch-button for more info
###
onWatch: ->
onSuccess = =>
@.loadEpic()
@rootscope.$broadcast("object:updated")
onError = =>
@confirm.notify("error")
return @rs.epics.watch(@scope.epicId).then(onSuccess, onError)
onUnwatch: ->
onSuccess = =>
@.loadEpic()
@rootscope.$broadcast("object:updated")
onError = =>
@confirm.notify("error")
return @rs.epics.unwatch(@scope.epicId).then(onSuccess, onError)
onSelectColor: (color) ->
onSelectColorSuccess = () =>
@rootscope.$broadcast("object:updated")
@confirm.notify('success')
onSelectColorError = () =>
@confirm.notify('error')
transform = @modelTransform.save (epic) ->
epic.color = color
return epic
return transform.then(onSelectColorSuccess, onSelectColorError)
module.controller("EpicDetailController", EpicDetailController)
#############################################################################
## Epic status display directive
#############################################################################
EpicStatusDisplayDirective = ($template, $compile) ->
# Display if an epic is open or closed and its status.
#
# Example:
# tg-epic-status-display(ng-model="epic")
#
# Requirements:
# - Epic object (ng-model)
# - scope.statusById object
template = $template.get("common/components/status-display.html", true)
link = ($scope, $el, $attrs) ->
render = (epic) ->
status = $scope.statusById[epic.status]
html = template({
is_closed: status.is_closed
status: status
})
html = $compile(html)($scope)
$el.html(html)
$scope.$watch $attrs.ngModel, (epic) ->
render(epic) if epic?
$scope.$on "$destroy", ->
$el.off()
return {
link: link
restrict: "EA"
require: "ngModel"
}
module.directive("tgEpicStatusDisplay", ["$tgTemplate", "$compile", EpicStatusDisplayDirective])
#############################################################################
## Epic status button directive
#############################################################################
EpicStatusButtonDirective = ($rootScope, $repo, $confirm, $loading, $modelTransform, $compile, $translate, $template) ->
# Display the status of epic and you can edit it.
#
# Example:
# tg-epic-status-button(ng-model="epic")
#
# Requirements:
# - Epic object (ng-model)
# - scope.statusById object
# - $scope.project.my_permissions
template = $template.get("common/components/status-button.html", true)
link = ($scope, $el, $attrs, $model) ->
isEditable = ->
return $scope.project.my_permissions.indexOf("modify_epic") != -1
render = (epic) =>
status = $scope.statusById[epic.status]
html = $compile(template({
status: status
statuses: $scope.statusList
editable: isEditable()
}))($scope)
$el.html(html)
save = (status) ->
currentLoading = $loading()
.target($el)
.start()
transform = $modelTransform.save (epic) ->
epic.status = status
return epic
onSuccess = ->
$rootScope.$broadcast("object:updated")
currentLoading.finish()
onError = ->
$confirm.notify("error")
currentLoading.finish()
transform.then(onSuccess, onError)
$el.on "click", ".js-edit-status", (event) ->
event.preventDefault()
event.stopPropagation()
return if not isEditable()
$el.find(".pop-status").popover().open()
$el.on "click", ".status", (event) ->
event.preventDefault()
event.stopPropagation()
return if not isEditable()
target = angular.element(event.currentTarget)
$.fn.popover().closeAll()
save(target.data("status-id"))
$scope.$watch () ->
return $model.$modelValue?.status
, () ->
epic = $model.$modelValue
render(epic) if epic
$scope.$on "$destroy", ->
$el.off()
return {
link: link
restrict: "EA"
require: "ngModel"
}
module.directive("tgEpicStatusButton", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgLoading", "$tgQueueModelTransformation",
"$compile", "$translate", "$tgTemplate", EpicStatusButtonDirective])

View File

@ -96,6 +96,7 @@ class EventsService
maxMissedHeartbeats = @config.get("eventsMaxMissedHeartbeats", 5) maxMissedHeartbeats = @config.get("eventsMaxMissedHeartbeats", 5)
heartbeatIntervalTime = @config.get("eventsHeartbeatIntervalTime", 60000) heartbeatIntervalTime = @config.get("eventsHeartbeatIntervalTime", 60000)
reconnectTryInterval = @config.get("eventsReconnectTryInterval", 10000)
@.missedHeartbeats = 0 @.missedHeartbeats = 0
@.heartbeatInterval = setInterval(() => @.heartbeatInterval = setInterval(() =>
@ -108,7 +109,7 @@ class EventsService
@log.debug("HeartBeat send PING") @log.debug("HeartBeat send PING")
catch e catch e
@log.error("HeartBeat error: " + e.message) @log.error("HeartBeat error: " + e.message)
@.stopHeartBeatMessages() @.setupConnection()
, heartbeatIntervalTime) , heartbeatIntervalTime)
@log.debug("HeartBeat enabled") @log.debug("HeartBeat enabled")
@ -228,11 +229,13 @@ class EventsService
onError: (error) -> onError: (error) ->
@log.error("WebSocket error: #{error}") @log.error("WebSocket error: #{error}")
@.error = true @.error = true
setTimeout(@.setupConnection, @.reconnectTryInterval)
onClose: -> onClose: ->
@log.debug("WebSocket closed.") @log.debug("WebSocket closed.")
@.connected = false @.connected = false
@.stopHeartBeatMessages() @.stopHeartBeatMessages()
setTimeout(@.setupConnection, @.reconnectTryInterval)
class EventsProvider class EventsProvider

View File

@ -52,11 +52,12 @@ class IssueDetailController extends mixOf(taiga.Controller, taiga.PageMixin)
"$tgAnalytics", "$tgAnalytics",
"$tgNavUrls", "$tgNavUrls",
"$translate", "$translate",
"$tgQueueModelTransformation" "$tgQueueModelTransformation",
"tgErrorHandlingService"
] ]
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location,
@log, @appMetaService, @analytics, @navUrls, @translate, @modelTransform) -> @log, @appMetaService, @analytics, @navUrls, @translate, @modelTransform, @errorHandlingService) ->
bindMethods(@) bindMethods(@)
@scope.issueRef = @params.issueref @scope.issueRef = @params.issueref

View File

@ -25,6 +25,7 @@
taiga = @.taiga taiga = @.taiga
bindOnce = @.taiga.bindOnce bindOnce = @.taiga.bindOnce
debounce = @.taiga.debounce debounce = @.taiga.debounce
trim = @.taiga.trim
module = angular.module("taigaIssues") module = angular.module("taigaIssues")
@ -44,8 +45,8 @@ CreateIssueDirective = ($repo, $confirm, $rootscope, lightboxService, $loading,
resetAttachments() resetAttachments()
$el.find(".tag-input").val("") $el.find(".tag-input").val("")
lightboxService.open $el, () ->
lightboxService.open($el) $scope.createIssueOpen = false
$scope.issue = { $scope.issue = {
project: project.id project: project.id
@ -57,10 +58,11 @@ CreateIssueDirective = ($repo, $confirm, $rootscope, lightboxService, $loading,
tags: [] tags: []
} }
$scope.createIssueOpen = true
$scope.$on "$destroy", -> $scope.$on "$destroy", ->
$el.off() $el.off()
createAttachments = (obj) -> createAttachments = (obj) ->
promises = _.map attachmentsToAdd.toJS(), (attachment) -> promises = _.map attachmentsToAdd.toJS(), (attachment) ->
return attachmentsService.upload(attachment.file, obj.id, $scope.issue.project, 'issue') return attachmentsService.upload(attachment.file, obj.id, $scope.issue.project, 'issue')
@ -76,6 +78,42 @@ CreateIssueDirective = ($repo, $confirm, $rootscope, lightboxService, $loading,
$scope.addAttachment = (attachment) -> $scope.addAttachment = (attachment) ->
attachmentsToAdd = attachmentsToAdd.push(attachment) attachmentsToAdd = attachmentsToAdd.push(attachment)
$scope.addTag = (tag, color) ->
value = trim(tag.toLowerCase())
tags = $scope.project.tags
projectTags = $scope.project.tags_colors
tags = [] if not tags?
projectTags = {} if not projectTags?
if value not in tags
tags.push(value)
projectTags[tag] = color || null
$scope.project.tags = tags
itemtags = _.clone($scope.issue.tags)
inserted = _.find itemtags, (it) -> it[0] == value
if !inserted
itemtags.push([tag , color])
$scope.issue.tags = itemtags
$scope.deleteTag = (tag) ->
value = trim(tag[0].toLowerCase())
tags = $scope.project.tags
itemtags = _.clone($scope.us.tags)
_.remove itemtags, (tag) -> tag[0] == value
$scope.us.tags = itemtags
_.pull($scope.issue.tags, value)
submit = debounce 2000, (event) => submit = debounce 2000, (event) =>
event.preventDefault() event.preventDefault()
@ -101,7 +139,6 @@ CreateIssueDirective = ($repo, $confirm, $rootscope, lightboxService, $loading,
currentLoading.finish() currentLoading.finish()
$confirm.notify("error") $confirm.notify("error")
submitButton = $el.find(".submit-button") submitButton = $el.find(".submit-button")
$el.on "submit", "form", submit $el.on "submit", "form", submit
@ -109,8 +146,8 @@ CreateIssueDirective = ($repo, $confirm, $rootscope, lightboxService, $loading,
return {link:link} return {link:link}
module.directive("tgLbCreateIssue", ["$tgRepo", "$tgConfirm", "$rootScope", "lightboxService", "$tgLoading", "$q", "tgAttachmentsService", module.directive("tgLbCreateIssue", ["$tgRepo", "$tgConfirm", "$rootScope", "lightboxService", "$tgLoading",
CreateIssueDirective]) "$q", "tgAttachmentsService", CreateIssueDirective])
############################################################################# #############################################################################

View File

@ -32,6 +32,7 @@ groupBy = @.taiga.groupBy
bindOnce = @.taiga.bindOnce bindOnce = @.taiga.bindOnce
debounceLeading = @.taiga.debounceLeading debounceLeading = @.taiga.debounceLeading
startswith = @.taiga.startswith startswith = @.taiga.startswith
bindMethods = @.taiga.bindMethods
module = angular.module("taigaIssues") module = angular.module("taigaIssues")
@ -54,20 +55,24 @@ class IssuesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi
"$tgNavUrls", "$tgNavUrls",
"$tgEvents", "$tgEvents",
"$tgAnalytics", "$tgAnalytics",
"$translate" "$translate",
"tgErrorHandlingService",
"$tgStorage",
"tgFilterRemoteStorageService"
] ]
filtersHashSuffix: "issues-filters"
myFiltersHashSuffix: "issues-my-filters"
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @urls, @params, @q, @location, @appMetaService, constructor: (@scope, @rootscope, @repo, @confirm, @rs, @urls, @params, @q, @location, @appMetaService,
@navUrls, @events, @analytics, @translate) -> @navUrls, @events, @analytics, @translate, @errorHandlingService, @storage, @filterRemoteStorageService) ->
bindMethods(@)
@scope.sectionName = "Issues" @scope.sectionName = "Issues"
@scope.filters = {} @scope.filters = {}
@.voting = false
if _.isEmpty(@location.search()) return if @.applyStoredFilters(@params.pslug, @.filtersHashSuffix)
filters = @rs.issues.getFilters(@params.pslug)
filters.page = 1
@location.search(filters)
@location.replace()
return
promise = @.loadInitialData() promise = @.loadInitialData()
@ -87,18 +92,207 @@ class IssuesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi
@analytics.trackEvent("issue", "create", "create issue on issues list", 1) @analytics.trackEvent("issue", "create", "create issue on issues list", 1)
@.loadIssues() @.loadIssues()
changeQ: (q) ->
@.unselectFilter("page")
@.replaceFilter("q", q)
@.loadIssues()
@.generateFilters()
removeFilter: (filter) ->
@.unselectFilter("page")
@.unselectFilter(filter.dataType, filter.id)
@.loadIssues()
@.generateFilters()
addFilter: (newFilter) ->
@.unselectFilter("page")
@.selectFilter(newFilter.category.dataType, newFilter.filter.id)
@.loadIssues()
@.generateFilters()
selectCustomFilter: (customFilter) ->
orderBy = @location.search().order_by
if orderBy
customFilter.filter.order_by = orderBy
@.unselectFilter("page")
@.replaceAllFilters(customFilter.filter)
@.loadIssues()
@.generateFilters()
removeCustomFilter: (customFilter) ->
console.log "oooo"
@filterRemoteStorageService.getFilters(@scope.projectId, @.myFiltersHashSuffix).then (userFilters) =>
console.log userFilters[customFilter.id]
delete userFilters[customFilter.id]
@filterRemoteStorageService.storeFilters(@scope.projectId, userFilters, @.myFiltersHashSuffix).then(@.generateFilters)
saveCustomFilter: (name) ->
filters = {}
urlfilters = @location.search()
filters.tags = urlfilters.tags
filters.status = urlfilters.status
filters.type = urlfilters.type
filters.severity = urlfilters.severity
filters.priority = urlfilters.priority
filters.assigned_to = urlfilters.assigned_to
filters.owner = urlfilters.owner
@filterRemoteStorageService.getFilters(@scope.projectId, @.myFiltersHashSuffix).then (userFilters) =>
userFilters[name] = filters
@filterRemoteStorageService.storeFilters(@scope.projectId, userFilters, @.myFiltersHashSuffix).then(@.generateFilters)
generateFilters: ->
@.storeFilters(@params.pslug, @location.search(), @.filtersHashSuffix)
urlfilters = @location.search()
loadFilters = {}
loadFilters.project = @scope.projectId
loadFilters.tags = urlfilters.tags
loadFilters.status = urlfilters.status
loadFilters.type = urlfilters.type
loadFilters.severity = urlfilters.severity
loadFilters.priority = urlfilters.priority
loadFilters.assigned_to = urlfilters.assigned_to
loadFilters.owner = urlfilters.owner
loadFilters.q = urlfilters.q
return @q.all([
@rs.issues.filtersData(loadFilters),
@filterRemoteStorageService.getFilters(@scope.projectId, @.myFiltersHashSuffix)
]).then (result) =>
data = result[0]
customFiltersRaw = result[1]
statuses = _.map data.statuses, (it) ->
it.id = it.id.toString()
return it
type = _.map data.types, (it) ->
it.id = it.id.toString()
return it
severity = _.map data.severities, (it) ->
it.id = it.id.toString()
return it
priority = _.map data.priorities, (it) ->
it.id = it.id.toString()
return it
tags = _.map data.tags, (it) ->
it.id = it.name
return it
tagsWithAtLeastOneElement = _.filter tags, (tag) ->
return tag.count > 0
assignedTo = _.map data.assigned_to, (it) ->
if it.id
it.id = it.id.toString()
else
it.id = "null"
it.name = it.full_name || "Unassigned"
return it
owner = _.map data.owners, (it) ->
it.id = it.id.toString()
it.name = it.full_name
return it
@.selectedFilters = []
if loadFilters.status
selected = @.formatSelectedFilters("status", statuses, loadFilters.status)
@.selectedFilters = @.selectedFilters.concat(selected)
if loadFilters.tags
selected = @.formatSelectedFilters("tags", tags, loadFilters.tags)
@.selectedFilters = @.selectedFilters.concat(selected)
if loadFilters.assigned_to
selected = @.formatSelectedFilters("assigned_to", assignedTo, loadFilters.assigned_to)
@.selectedFilters = @.selectedFilters.concat(selected)
if loadFilters.owner
selected = @.formatSelectedFilters("owner", owner, loadFilters.owner)
@.selectedFilters = @.selectedFilters.concat(selected)
if loadFilters.type
selected = @.formatSelectedFilters("type", type, loadFilters.type)
@.selectedFilters = @.selectedFilters.concat(selected)
if loadFilters.severity
selected = @.formatSelectedFilters("severity", severity, loadFilters.severity)
@.selectedFilters = @.selectedFilters.concat(selected)
if loadFilters.priority
selected = @.formatSelectedFilters("priority", priority, loadFilters.priority)
@.selectedFilters = @.selectedFilters.concat(selected)
@.filterQ = loadFilters.q
@.filters = [
{
title: @translate.instant("COMMON.FILTERS.CATEGORIES.TYPE"),
dataType: "type",
content: type
},
{
title: @translate.instant("COMMON.FILTERS.CATEGORIES.SEVERITY"),
dataType: "severity",
content: severity
},
{
title: @translate.instant("COMMON.FILTERS.CATEGORIES.PRIORITIES"),
dataType: "priority",
content: priority
},
{
title: @translate.instant("COMMON.FILTERS.CATEGORIES.STATUS"),
dataType: "status",
content: statuses
},
{
title: @translate.instant("COMMON.FILTERS.CATEGORIES.TAGS"),
dataType: "tags",
content: tags,
hideEmpty: true,
totalTaggedElements: tagsWithAtLeastOneElement.length
},
{
title: @translate.instant("COMMON.FILTERS.CATEGORIES.ASSIGNED_TO"),
dataType: "assigned_to",
content: assignedTo
},
{
title: @translate.instant("COMMON.FILTERS.CATEGORIES.CREATED_BY"),
dataType: "owner",
content: owner
}
]
@.customFilters = []
_.forOwn customFiltersRaw, (value, key) =>
@.customFilters.push({id: key, name: key, filter: value})
initializeSubscription: -> initializeSubscription: ->
routingKey = "changes.project.#{@scope.projectId}.issues" routingKey = "changes.project.#{@scope.projectId}.issues"
@events.subscribe @scope, routingKey, (message) => @events.subscribe @scope, routingKey, (message) =>
@.loadIssues() @.loadIssues()
storeFilters: ->
@rs.issues.storeFilters(@params.pslug, @location.search())
loadProject: -> loadProject: ->
return @rs.projects.getBySlug(@params.pslug).then (project) => return @rs.projects.getBySlug(@params.pslug).then (project) =>
if not project.is_issues_activated if not project.is_issues_activated
@location.path(@navUrls.resolve("permission-denied")) @errorHandlingService.permissionDenied()
@scope.projectId = project.id @scope.projectId = project.id
@scope.project = project @scope.project = project
@ -115,160 +309,15 @@ class IssuesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi
return project return project
getUrlFilters: ->
filters = _.pick(@location.search(), "page", "tags", "status", "types",
"q", "severities", "priorities",
"assignedTo", "createdBy", "orderBy")
filters.page = 1 if not filters.page
return filters
getUrlFilter: (name) ->
filters = _.pick(@location.search(), name)
return filters[name]
loadMyFilters: ->
return @rs.issues.getMyFilters(@scope.projectId).then (filters) =>
return _.map filters, (value, key) =>
return {id: key, name: key, type: "myFilters", selected: false}
removeNotExistingFiltersFromUrl: ->
currentSearch = @location.search()
urlfilters = @.getUrlFilters()
for filterName, filterValue of urlfilters
if filterName == "page" or filterName == "orderBy" or filterName == "q"
continue
if filterName == "tags"
splittedValues = _.map("#{filterValue}".split(","))
else
splittedValues = _.map("#{filterValue}".split(","), (x) -> if x == "null" then null else parseInt(x))
existingValues = _.intersection(splittedValues, _.map(@scope.filters[filterName], "id"))
if splittedValues.length != existingValues.length
@location.search(filterName, existingValues.join())
if currentSearch != @location.search()
@location.replace()
markSelectedFilters: (filters, urlfilters) ->
# Build selected filters (from url) fast lookup data structure
searchdata = {}
for name, value of _.omit(urlfilters, "page", "orderBy")
if not searchdata[name]?
searchdata[name] = {}
for val in "#{value}".split(",")
searchdata[name][val] = true
isSelected = (type, id) ->
if searchdata[type]? and searchdata[type][id]
return true
return false
for key, value of filters
for obj in value
obj.selected = if isSelected(obj.type, obj.id) then true else undefined
loadFilters: () ->
urlfilters = @.getUrlFilters()
if urlfilters.q
@scope.filtersQ = urlfilters.q
# Load My Filters
promise = @.loadMyFilters().then (myFilters) =>
@scope.filters.myFilters = myFilters
return myFilters
loadFilters = {}
loadFilters.project = @scope.projectId
loadFilters.tags = urlfilters.tags
loadFilters.status = urlfilters.status
loadFilters.q = urlfilters.q
loadFilters.types = urlfilters.types
loadFilters.severities = urlfilters.severities
loadFilters.priorities = urlfilters.priorities
loadFilters.assigned_to = urlfilters.assignedTo
loadFilters.owner = urlfilters.createdBy
# Load default filters data
promise = promise.then =>
return @rs.issues.filtersData(loadFilters)
# Format filters and set them on scope
return promise.then (data) =>
usersFiltersFormat = (users, type, unknownOption) =>
reformatedUsers = _.map users, (t) =>
t.type = type
t.name = if t.full_name then t.full_name else unknownOption
return t
unknownItem = _.remove(reformatedUsers, (u) -> not u.id)
reformatedUsers = _.sortBy(reformatedUsers, (u) -> u.name.toUpperCase())
if unknownItem.length > 0
reformatedUsers.unshift(unknownItem[0])
return reformatedUsers
choicesFiltersFormat = (choices, type, byIdObject) =>
_.map choices, (t) ->
t.type = type
return t
tagsFilterFormat = (tags) =>
return _.map tags, (t) ->
t.id = t.name
t.type = 'tags'
return t
# Build filters data structure
@scope.filters.status = choicesFiltersFormat(data.statuses, "status", @scope.issueStatusById)
@scope.filters.severities = choicesFiltersFormat(data.severities, "severities", @scope.severityById)
@scope.filters.priorities = choicesFiltersFormat(data.priorities, "priorities", @scope.priorityById)
@scope.filters.assignedTo = usersFiltersFormat(data.assigned_to, "assignedTo", "Unassigned")
@scope.filters.createdBy = usersFiltersFormat(data.owners, "createdBy", "Unknown")
@scope.filters.types = choicesFiltersFormat(data.types, "types", @scope.issueTypeById)
@scope.filters.tags = tagsFilterFormat(data.tags)
@.removeNotExistingFiltersFromUrl()
@.markSelectedFilters(@scope.filters, urlfilters)
@rootscope.$broadcast("filters:loaded", @scope.filters)
# We need to guarantee that the last petition done here is the finally used # We need to guarantee that the last petition done here is the finally used
# When searching by text loadIssues can be called fastly with different parameters and # When searching by text loadIssues can be called fastly with different parameters and
# can be resolved in a different order than generated # can be resolved in a different order than generated
# We count the requests made and only if the callback is for the last one data is updated # We count the requests made and only if the callback is for the last one data is updated
loadIssuesRequests: 0 loadIssuesRequests: 0
loadIssues: => loadIssues: =>
@scope.urlFilters = @.getUrlFilters() params = @location.search()
# Convert stored filters to http parameters promise = @rs.issues.list(@scope.projectId, params)
# ready filters (the name difference exists
# because of some automatic lookups and is
# the simplest way todo it without adding
# additional complexity to code.
@scope.httpParams = {}
for name, values of @scope.urlFilters
if name == "severities"
name = "severity"
else if name == "orderBy"
name = "order_by"
else if name == "priorities"
name = "priority"
else if name == "assignedTo"
name = "assigned_to"
else if name == "createdBy"
name = "owner"
else if name == "status"
name = "status"
else if name == "types"
name = "type"
@scope.httpParams[name] = values
promise = @rs.issues.list(@scope.projectId, @scope.httpParams)
@.loadIssuesRequests += 1 @.loadIssuesRequests += 1
promise.index = @.loadIssuesRequests promise.index = @.loadIssuesRequests
promise.then (data) => promise.then (data) =>
@ -287,26 +336,10 @@ class IssuesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi
return promise.then (project) => return promise.then (project) =>
@.fillUsersAndRoles(project.members, project.roles) @.fillUsersAndRoles(project.members, project.roles)
@.initializeSubscription() @.initializeSubscription()
@.loadFilters() @.generateFilters()
return @.loadIssues() return @.loadIssues()
saveCurrentFiltersTo: (newFilter) ->
deferred = @q.defer()
@rs.issues.getMyFilters(@scope.projectId).then (filters) =>
filters[newFilter] = @location.search()
@rs.issues.storeMyFilters(@scope.projectId, filters).then =>
deferred.resolve()
return deferred.promise
deleteMyFilter: (filter) ->
deferred = @q.defer()
@rs.issues.getMyFilters(@scope.projectId).then (filters) =>
delete filters[filter]
@rs.issues.storeMyFilters(@scope.projectId, filters).then =>
deferred.resolve()
return deferred.promise
# Functions used from templates # Functions used from templates
addNewIssue: -> addNewIssue: ->
@rootscope.$broadcast("issueform:new", @scope.project) @rootscope.$broadcast("issueform:new", @scope.project)
@ -314,6 +347,33 @@ class IssuesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi
addIssuesInBulk: -> addIssuesInBulk: ->
@rootscope.$broadcast("issueform:bulk", @scope.projectId) @rootscope.$broadcast("issueform:bulk", @scope.projectId)
upVoteIssue: (issueId) ->
@.voting = issueId
onSuccess = =>
@.loadIssues()
@.voting = null
onError = =>
@confirm.notify("error")
@.voting = null
return @rs.issues.upvote(issueId).then(onSuccess, onError)
downVoteIssue: (issueId) ->
@.voting = issueId
onSuccess = =>
@.loadIssues()
@.voting = null
onError = =>
@confirm.notify("error")
@.voting = null
return @rs.issues.downvote(issueId).then(onSuccess, onError)
getOrderBy: ->
if _.isString(@location.search().order_by)
return @location.search().order_by
else
return "created_date"
module.controller("IssuesController", IssuesController) module.controller("IssuesController", IssuesController)
@ -408,28 +468,40 @@ IssuesDirective = ($log, $location, $template, $compile) ->
## Issues Filters ## Issues Filters
linkOrdering = ($scope, $el, $attrs, $ctrl) -> linkOrdering = ($scope, $el, $attrs, $ctrl) ->
# Draw the arrow the first time # Draw the arrow the first time
currentOrder = $ctrl.getUrlFilter("orderBy") or "created_date"
currentOrder = $ctrl.getOrderBy()
if currentOrder if currentOrder
icon = if startswith(currentOrder, "-") then "icon-arrow-up" else "icon-arrow-bottom" icon = if startswith(currentOrder, "-") then "icon-arrow-up" else "icon-arrow-down"
colHeadElement = $el.find(".row.title > div[data-fieldname='#{trim(currentOrder, "-")}']") colHeadElement = $el.find(".row.title > div[data-fieldname='#{trim(currentOrder, "-")}']")
colHeadElement.html("#{colHeadElement.html()}<span class='icon #{icon}'></span>")
svg = $("<tg-svg>").attr("svg-icon", icon)
colHeadElement.append(svg)
$compile(colHeadElement.contents())($scope)
$el.on "click", ".row.title > div", (event) -> $el.on "click", ".row.title > div", (event) ->
target = angular.element(event.currentTarget) target = angular.element(event.currentTarget)
currentOrder = $ctrl.getUrlFilter("orderBy") currentOrder = $ctrl.getOrderBy()
newOrder = target.data("fieldname") newOrder = target.data("fieldname")
finalOrder = if currentOrder == newOrder then "-#{newOrder}" else newOrder finalOrder = if currentOrder == newOrder then "-#{newOrder}" else newOrder
$scope.$apply -> $scope.$apply ->
$ctrl.replaceFilter("orderBy", finalOrder) $ctrl.replaceFilter("order_by", finalOrder)
$ctrl.storeFilters()
$ctrl.storeFilters($ctrl.params.pslug, $location.search(), $ctrl.filtersHashSuffix)
$ctrl.loadIssues().then -> $ctrl.loadIssues().then ->
# Update the arrow # Update the arrow
$el.find(".row.title > div > span.icon").remove() $el.find(".row.title > div > tg-svg").remove()
icon = if startswith(finalOrder, "-") then "icon-arrow-up" else "icon-arrow-bottom" icon = if startswith(finalOrder, "-") then "icon-arrow-up" else "icon-arrow-down"
target.html("#{target.html()}<span class='icon #{icon}'></span>")
svg = $("<tg-svg>")
.attr("svg-icon", icon)
target.append(svg)
$compile(target.contents())($scope)
## Issues Link ## Issues Link
link = ($scope, $el, $attrs) -> link = ($scope, $el, $attrs) ->
@ -445,253 +517,6 @@ IssuesDirective = ($log, $location, $template, $compile) ->
module.directive("tgIssues", ["$log", "$tgLocation", "$tgTemplate", "$compile", IssuesDirective]) module.directive("tgIssues", ["$log", "$tgLocation", "$tgTemplate", "$compile", IssuesDirective])
#############################################################################
## Issues Filters Directive
#############################################################################
IssuesFiltersDirective = ($q, $log, $location, $rs, $confirm, $loading, $template, $translate, $compile, $auth) ->
template = $template.get("issue/issues-filters.html", true)
templateSelected = $template.get("issue/issues-filters-selected.html", true)
link = ($scope, $el, $attrs) ->
$ctrl = $el.closest(".wrapper").controller()
selectedFilters = []
showFilters = (title, type) ->
$el.find(".filters-cats").hide()
$el.find(".filter-list").removeClass("hidden")
$el.find(".breadcrumb").removeClass("hidden")
$el.find("h2 .subfilter .title").html(title)
$el.find("h2 .subfilter .title").prop("data-type", type)
showCategories = ->
$el.find(".filters-cats").show()
$el.find(".filter-list").addClass("hidden")
$el.find(".breadcrumb").addClass("hidden")
initializeSelectedFilters = (filters) ->
selectedFilters = []
for name, values of filters
for val in values
selectedFilters.push(val) if val.selected
renderSelectedFilters(selectedFilters)
renderSelectedFilters = (selectedFilters) ->
_.filter selectedFilters, (f) =>
if f.color
f.style = "border-left: 3px solid #{f.color}"
html = templateSelected({filters:selectedFilters})
html = $compile(html)($scope)
$el.find(".filters-applied").html(html)
if $auth.isAuthenticated() && selectedFilters.length > 0
$el.find(".save-filters").show()
else
$el.find(".save-filters").hide()
renderFilters = (filters) ->
_.filter filters, (f) =>
if f.color
f.style = "border-left: 3px solid #{f.color}"
html = template({filters:filters})
html = $compile(html)($scope)
$el.find(".filter-list").html(html)
getFiltersType = () ->
return $el.find(".subfilter .title").prop('data-type')
reloadIssues = () ->
currentFiltersType = getFiltersType()
$q.all([$ctrl.loadIssues(), $ctrl.loadFilters()]).then () ->
filters = $scope.filters[currentFiltersType]
renderFilters(_.reject(filters, "selected"))
toggleFilterSelection = (type, id) ->
if type == "myFilters"
$rs.issues.getMyFilters($scope.projectId).then (data) ->
myFilters = data
filters = myFilters[id]
filters.page = 1
$ctrl.replaceAllFilters(filters)
$ctrl.storeFilters()
$ctrl.loadIssues()
$ctrl.markSelectedFilters($scope.filters, filters)
initializeSelectedFilters($scope.filters)
return null
filters = $scope.filters[type]
filterId = if type == 'tags' then taiga.toString(id) else id
filter = _.find(filters, {id: filterId})
filter.selected = (not filter.selected)
# Convert id to null as string for properly
# put null value on url parameters
id = "null" if id is null
if filter.selected
selectedFilters.push(filter)
$ctrl.selectFilter(type, id)
$ctrl.selectFilter("page", 1)
$ctrl.storeFilters()
else
selectedFilters = _.reject selectedFilters, (f) ->
return f.id == filter.id && f.type == filter.type
$ctrl.unselectFilter(type, id)
$ctrl.selectFilter("page", 1)
$ctrl.storeFilters()
reloadIssues()
renderSelectedFilters(selectedFilters)
currentFiltersType = getFiltersType()
if type == currentFiltersType
renderFilters(_.reject(filters, "selected"))
# Angular Watchers
$scope.$on "filters:loaded", (ctx, filters) ->
initializeSelectedFilters(filters)
$scope.$on "filters:issueupdate", (ctx, filters) ->
html = template({filters:filters.status})
html = $compile(html)($scope)
$el.find(".filter-list").html(html)
selectQFilter = debounceLeading 100, (value, oldValue) ->
return if value is undefined or value == oldValue
$ctrl.replaceFilter("page", null, true)
if value.length == 0
$ctrl.replaceFilter("q", null)
$ctrl.storeFilters()
else
$ctrl.replaceFilter("q", value)
$ctrl.storeFilters()
reloadIssues()
unwatchIssues = $scope.$watch "issues", (newValue) ->
if !_.isUndefined(newValue)
$scope.$watch("filtersQ", selectQFilter)
unwatchIssues()
# Dom Event Handlers
$el.on "click", ".filters-cat-single", (event) ->
event.preventDefault()
target = angular.element(event.currentTarget)
tags = $scope.filters[target.data("type")]
renderFilters(_.reject(tags, "selected"))
showFilters(target.attr("title"), target.data("type"))
$el.on "click", ".back", (event) ->
event.preventDefault()
showCategories($el)
$el.on "click", ".filters-applied .remove-filter", (event) ->
event.preventDefault()
target = angular.element(event.currentTarget).parent()
id = target.data("id") or null
type = target.data("type")
toggleFilterSelection(type, id)
$el.on "click", ".filter-list .single-filter", (event) ->
event.preventDefault()
target = angular.element(event.currentTarget)
target.toggleClass("active")
id = target.data("id") or null
type = target.data("type")
# A saved filter can't be active
if type == "myFilters"
target.removeClass("active")
toggleFilterSelection(type, id)
$el.on "click", ".filter-list .remove-filter", (event) ->
event.preventDefault()
event.stopPropagation()
target = angular.element(event.currentTarget)
customFilterName = target.parent().data('id')
title = $translate.instant("ISSUES.FILTERS.CONFIRM_DELETE.TITLE")
message = $translate.instant("ISSUES.FILTERS.CONFIRM_DELETE.MESSAGE", {customFilterName: customFilterName})
$confirm.askOnDelete(title, message).then (askResponse) ->
promise = $ctrl.deleteMyFilter(customFilterName)
promise.then ->
promise = $ctrl.loadMyFilters()
promise.then (filters) ->
askResponse.finish()
$scope.filters.myFilters = filters
renderFilters($scope.filters.myFilters)
promise.then null, ->
askResponse.finish()
promise.then null, ->
askResponse.finish(false)
$confirm.notify("error")
$el.on "click", ".save-filters", (event) ->
event.preventDefault()
renderFilters($scope.filters["myFilters"])
showFilters("My filters", "myFilters")
$el.find('.save-filters').hide()
$el.find('.my-filter-name').removeClass("hidden")
$el.find('.my-filter-name').focus()
$scope.$apply()
$el.on "keyup", ".my-filter-name", (event) ->
event.preventDefault()
if event.keyCode == 13
target = angular.element(event.currentTarget)
newFilter = target.val()
currentLoading = $loading()
.target($el.find(".new"))
.start()
promise = $ctrl.saveCurrentFiltersTo(newFilter)
promise.then ->
loadPromise = $ctrl.loadMyFilters()
loadPromise.then (filters) ->
currentLoading.finish()
$scope.filters.myFilters = filters
currentfilterstype = $el.find("h2 .subfilter .title").prop('data-type')
if currentfilterstype == "myFilters"
renderFilters($scope.filters.myFilters)
$el.find('.my-filter-name').addClass("hidden")
$el.find('.save-filters').show()
loadPromise.then null, ->
currentLoading.finish()
$confirm.notify("error", "Error loading custom filters")
promise.then null, ->
currentLoading.finish()
$el.find(".my-filter-name").val(newFilter).focus().select()
$confirm.notify("error", "Filter not saved")
else if event.keyCode == 27
$el.find('.my-filter-name').val('')
$el.find('.my-filter-name').addClass("hidden")
$el.find('.save-filters').show()
return {link:link}
module.directive("tgIssuesFilters", ["$q", "$log", "$tgLocation", "$tgResources", "$tgConfirm", "$tgLoading",
"$tgTemplate", "$translate", "$compile", "$tgAuth", IssuesFiltersDirective])
############################################################################# #############################################################################
## Issue status Directive (popover for change status) ## Issue status Directive (popover for change status)
############################################################################# #############################################################################
@ -778,9 +603,9 @@ module.directive("tgIssueStatusInlineEdition", ["$tgRepo", "$tgTemplate", "$root
## Issue assigned to Directive ## Issue assigned to Directive
############################################################################# #############################################################################
IssueAssignedToInlineEditionDirective = ($repo, $rootscope, $translate) -> IssueAssignedToInlineEditionDirective = ($repo, $rootscope, $translate, avatarService) ->
template = _.template(""" template = _.template("""
<img src="<%- imgurl %>" alt="<%- name %>"/> <img style="background-color: <%- bg %>" src="<%- imgurl %>" alt="<%- name %>"/>
<figcaption><%- name %></figcaption> <figcaption><%- name %></figcaption>
""") """)
@ -792,9 +617,14 @@ IssueAssignedToInlineEditionDirective = ($repo, $rootscope, $translate) ->
} }
member = $scope.usersById[issue.assigned_to] member = $scope.usersById[issue.assigned_to]
avatar = avatarService.getAvatar(member)
ctx.imgurl = avatar.url
ctx.bg = null
if member if member
ctx.name = member.full_name_display ctx.name = member.full_name_display
ctx.imgurl = member.photo ctx.bg = avatar.bg
$el.find(".avatar").html(template(ctx)) $el.find(".avatar").html(template(ctx))
$el.find(".issue-assignedto").attr('title', ctx.name) $el.find(".issue-assignedto").attr('title', ctx.name)
@ -826,5 +656,5 @@ IssueAssignedToInlineEditionDirective = ($repo, $rootscope, $translate) ->
return {link: link} return {link: link}
module.directive("tgIssueAssignedToInlineEdition", ["$tgRepo", "$rootScope", "$translate" module.directive("tgIssueAssignedToInlineEdition", ["$tgRepo", "$rootScope", "$translate", "tgAvatarService",
IssueAssignedToInlineEditionDirective]) IssueAssignedToInlineEditionDirective])

View File

@ -0,0 +1,188 @@
###
# Copyright (C) 2014-2016 Taiga Agile LLC <taiga@taiga.io>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# File: kanban-userstories.service.coffee
###
groupBy = @.taiga.groupBy
class KanbanUserstoriesService extends taiga.Service
@.$inject = []
constructor: () ->
@.reset()
reset: () ->
@.userstoriesRaw = []
@.archivedStatus = []
@.statusHide = []
@.foldStatusChanged = {}
@.usByStatus = Immutable.Map()
init: (project, usersById) ->
@.project = project
@.usersById = usersById
resetFolds: () ->
@.foldStatusChanged = {}
@.refresh()
toggleFold: (usId) ->
@.foldStatusChanged[usId] = !@.foldStatusChanged[usId]
@.refresh()
set: (userstories) ->
@.userstoriesRaw = userstories
@.refreshRawOrder()
@.refresh()
add: (us) ->
@.userstoriesRaw = @.userstoriesRaw.concat(us)
@.refreshRawOrder()
@.refresh()
addArchivedStatus: (statusId) ->
@.archivedStatus.push(statusId)
isUsInArchivedHiddenStatus: (usId) ->
us = @.getUsModel(usId)
return @.archivedStatus.indexOf(us.status) != -1 &&
@.statusHide.indexOf(us.status) != -1
hideStatus: (statusId) ->
@.deleteStatus(statusId)
@.statusHide.push(statusId)
showStatus: (statusId) ->
_.remove @.statusHide, (it) -> return it == statusId
getStatus: (statusId) ->
return _.filter @.userstoriesRaw, (us) -> return us.status == statusId
deleteStatus: (statusId) ->
toDelete = _.filter @.userstoriesRaw, (us) -> return us.status == statusId
toDelete = _.map (it) -> return it.id
@.archived = _.difference(@.archived, toDelete)
@.userstoriesRaw = _.filter @.userstoriesRaw, (us) -> return us.status != statusId
@.refresh()
refreshRawOrder: () ->
@.order = {}
@.order[it.id] = it.kanban_order for it in @.userstoriesRaw
assignOrders: (order) ->
order = _.invert(order)
@.order = _.assign(@.order, order)
@.refresh()
move: (id, statusId, index) ->
us = @.getUsModel(id)
usByStatus = _.filter @.userstoriesRaw, (it) =>
return it.status == statusId
usByStatus = _.sortBy usByStatus, (it) => @.order[it.id]
usByStatusWithoutMoved = _.filter usByStatus, (it) => it.id != id
beforeDestination = _.slice(usByStatusWithoutMoved, 0, index)
afterDestination = _.slice(usByStatusWithoutMoved, index)
setOrders = {}
previous = beforeDestination[beforeDestination.length - 1]
previousWithTheSameOrder = _.filter beforeDestination, (it) =>
@.order[it.id] == @.order[previous.id]
if previousWithTheSameOrder.length > 1
for it in previousWithTheSameOrder
setOrders[it.id] = @.order[it.id]
if !previous
@.order[us.id] = 0
else if previous
@.order[us.id] = @.order[previous.id] + 1
for it, key in afterDestination
@.order[it.id] = @.order[us.id] + key + 1
us.status = statusId
us.kanban_order = @.order[us.id]
@.refresh()
return {"us_id": us.id, "order": @.order[us.id], "set_orders": setOrders}
replace: (us) ->
@.usByStatus = @.usByStatus.map (status) ->
findedIndex = status.findIndex (usItem) ->
return usItem.get('id') == us.get('id')
if findedIndex != -1
status = status.set(findedIndex, us)
return status
replaceModel: (us) ->
@.userstoriesRaw = _.map @.userstoriesRaw, (usItem) ->
if us.id == usItem.id
return us
else
return usItem
@.refresh()
getUs: (id) ->
findedUs = null
@.usByStatus.forEach (status) ->
findedUs = status.find (us) -> return us.get('id') == id
return false if findedUs
return findedUs
getUsModel: (id) ->
return _.find @.userstoriesRaw, (us) -> return us.id == id
refresh: ->
@.userstoriesRaw = _.sortBy @.userstoriesRaw, (it) => @.order[it.id]
userstories = @.userstoriesRaw
userstories = _.map userstories, (usModel) =>
us = {}
us.foldStatusChanged = @.foldStatusChanged[usModel.id]
us.model = usModel.getAttrs()
us.images = _.filter usModel.attachments, (it) -> return !!it.thumbnail_card_url
us.id = usModel.id
us.assigned_to = @.usersById[usModel.assigned_to]
us.colorized_tags = _.map us.model.tags, (tag) =>
return {name: tag[0], color: tag[1]}
return us
usByStatus = _.groupBy userstories, (us) ->
return us.model.status
@.usByStatus = Immutable.fromJS(usByStatus)
angular.module("taigaKanban").service("tgKanbanUserstories", KanbanUserstoriesService)

View File

@ -34,26 +34,18 @@ bindMethods = @.taiga.bindMethods
module = angular.module("taigaKanban") module = angular.module("taigaKanban")
# Vars
defaultViewMode = "maximized"
viewModes = [
"maximized",
"minimized"
]
############################################################################# #############################################################################
## Kanban Controller ## Kanban Controller
############################################################################# #############################################################################
class KanbanController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.FiltersMixin) class KanbanController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.FiltersMixin, taiga.UsFiltersMixin)
@.$inject = [ @.$inject = [
"$scope", "$scope",
"$rootScope", "$rootScope",
"$tgRepo", "$tgRepo",
"$tgConfirm", "$tgConfirm",
"$tgResources", "$tgResources",
"tgResources",
"$routeParams", "$routeParams",
"$q", "$q",
"$tgLocation", "$tgLocation",
@ -61,16 +53,27 @@ class KanbanController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi
"$tgNavUrls", "$tgNavUrls",
"$tgEvents", "$tgEvents",
"$tgAnalytics", "$tgAnalytics",
"$translate" "$translate",
"tgErrorHandlingService",
"$tgModel",
"tgKanbanUserstories",
"$tgStorage",
"tgFilterRemoteStorageService"
] ]
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, storeCustomFiltersName: 'kanban-custom-filters'
@appMetaService, @navUrls, @events, @analytics, @translate) -> storeFiltersName: 'kanban-filters'
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @rs2, @params, @q, @location,
@appMetaService, @navUrls, @events, @analytics, @translate, @errorHandlingService,
@model, @kanbanUserstoriesService, @storage, @filterRemoteStorageService) ->
bindMethods(@) bindMethods(@)
@kanbanUserstoriesService.reset()
@.openFilter = false
return if @.applyStoredFilters(@params.pslug, "kanban-filters")
@scope.sectionName = @translate.instant("KANBAN.SECTION_NAME") @scope.sectionName = @translate.instant("KANBAN.SECTION_NAME")
@scope.statusViewModes = {}
@.initializeEventHandlers() @.initializeEventHandlers()
promise = @.loadInitialData() promise = @.loadInitialData()
@ -87,80 +90,109 @@ class KanbanController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi
# On Error # On Error
promise.then null, @.onInitialDataError.bind(@) promise.then null, @.onInitialDataError.bind(@)
taiga.defineImmutableProperty @.scope, "usByStatus", () =>
return @kanbanUserstoriesService.usByStatus
setZoom: (zoomLevel, zoom) ->
if @.zoomLevel != zoomLevel
@kanbanUserstoriesService.resetFolds()
@.zoomLevel = zoomLevel
@.zoom = zoom
filtersReloadContent: () ->
@.loadUserstories().then () =>
openArchived = _.difference(@kanbanUserstoriesService.archivedStatus,
@kanbanUserstoriesService.statusHide)
if openArchived.length
for statusId in openArchived
@.loadUserStoriesForStatus({}, statusId)
initializeEventHandlers: -> initializeEventHandlers: ->
@scope.$on "usform:new:success", => @scope.$on "usform:new:success", (event, us) =>
@.loadUserstories() @.refreshTagsColors().then () =>
@.refreshTagsColors() @kanbanUserstoriesService.add(us)
@analytics.trackEvent("userstory", "create", "create userstory on kanban", 1) @analytics.trackEvent("userstory", "create", "create userstory on kanban", 1)
@scope.$on "usform:bulk:success", => @scope.$on "usform:bulk:success", (event, uss) =>
@.loadUserstories() @.refreshTagsColors().then () =>
@kanbanUserstoriesService.add(uss)
@analytics.trackEvent("userstory", "create", "bulk create userstory on kanban", 1) @analytics.trackEvent("userstory", "create", "bulk create userstory on kanban", 1)
@scope.$on "usform:edit:success", => @scope.$on "usform:edit:success", (event, us) =>
@.loadUserstories() @.refreshTagsColors().then () =>
@.refreshTagsColors() @kanbanUserstoriesService.replaceModel(us)
@scope.$on("assigned-to:added", @.onAssignedToChanged) @scope.$on("assigned-to:added", @.onAssignedToChanged)
@scope.$on("kanban:us:move", @.moveUs) @scope.$on("kanban:us:move", @.moveUs)
@scope.$on("kanban:show-userstories-for-status", @.loadUserStoriesForStatus) @scope.$on("kanban:show-userstories-for-status", @.loadUserStoriesForStatus)
@scope.$on("kanban:hide-userstories-for-status", @.hideUserStoriesForStatus) @scope.$on("kanban:hide-userstories-for-status", @.hideUserStoriesForStatus)
# Template actions
addNewUs: (type, statusId) -> addNewUs: (type, statusId) ->
switch type switch type
when "standard" then @rootscope.$broadcast("usform:new", @scope.projectId, statusId, @scope.usStatusList) when "standard" then @rootscope.$broadcast("usform:new",
when "bulk" then @rootscope.$broadcast("usform:bulk", @scope.projectId, statusId) @scope.projectId, statusId, @scope.usStatusList)
when "bulk" then @rootscope.$broadcast("usform:bulk",
@scope.projectId, statusId)
editUs: (id) ->
us = @kanbanUserstoriesService.getUs(id)
us = us.set('loading', true)
@kanbanUserstoriesService.replace(us)
@rs.userstories.getByRef(us.getIn(['model', 'project']), us.getIn(['model', 'ref']))
.then (editingUserStory) =>
@rs2.attachments.list("us", us.get('id'), us.getIn(['model', 'project'])).then (attachments) =>
@rootscope.$broadcast("usform:edit", editingUserStory, attachments.toJS())
us = us.set('loading', false)
@kanbanUserstoriesService.replace(us)
showPlaceHolder: (statusId) ->
if @scope.usStatusList[0].id == statusId &&
!@kanbanUserstoriesService.userstoriesRaw.length
return true
return false
toggleFold: (id) ->
@kanbanUserstoriesService.toggleFold(id)
isUsInArchivedHiddenStatus: (usId) ->
return @kanbanUserstoriesService.isUsInArchivedHiddenStatus(usId)
changeUsAssignedTo: (id) ->
us = @kanbanUserstoriesService.getUsModel(id)
changeUsAssignedTo: (us) ->
@rootscope.$broadcast("assigned-to:add", us) @rootscope.$broadcast("assigned-to:add", us)
# Scope Events Handlers onAssignedToChanged: (ctx, userid, usModel) ->
usModel.assigned_to = userid
onAssignedToChanged: (ctx, userid, us) -> @kanbanUserstoriesService.replaceModel(usModel)
us.assigned_to = userid
promise = @repo.save(us) promise = @repo.save(usModel)
promise.then null, -> promise.then null, ->
console.log "FAIL" # TODO console.log "FAIL" # TODO
# Load data methods
refreshTagsColors: -> refreshTagsColors: ->
return @rs.projects.tagsColors(@scope.projectId).then (tags_colors) => return @rs.projects.tagsColors(@scope.projectId).then (tags_colors) =>
@scope.project.tags_colors = tags_colors @scope.project.tags_colors = tags_colors._attrs
loadUserstories: -> loadUserstories: ->
params = { params = {
status__is_archived: false status__is_archived: false,
include_attachments: true,
include_tasks: true
} }
params = _.merge params, @location.search()
promise = @rs.userstories.listAll(@scope.projectId, params).then (userstories) => promise = @rs.userstories.listAll(@scope.projectId, params).then (userstories) =>
@scope.userstories = userstories @kanbanUserstoriesService.init(@scope.project, @scope.usersById)
@kanbanUserstoriesService.set(userstories)
usByStatus = _.groupBy(userstories, "status")
us_archived = []
for status in @scope.usStatusList
if not usByStatus[status.id]?
usByStatus[status.id] = []
if @scope.usByStatus?
for us in @scope.usByStatus[status.id]
if us.status != status.id
us_archived.push(us)
# Must preserve the archived columns if loaded
if status.is_archived and @scope.usByStatus? and @scope.usByStatus[status.id].length != 0
for us in @scope.usByStatus[status.id].concat(us_archived)
if us.status == status.id
usByStatus[status.id].push(us)
usByStatus[status.id] = _.sortBy(usByStatus[status.id], "kanban_order")
if userstories.length == 0
status = @scope.usStatusList[0]
usByStatus[status.id].push({isPlaceholder: true})
@scope.usByStatus = usByStatus
# The broadcast must be executed when the DOM has been fully reloaded. # The broadcast must be executed when the DOM has been fully reloaded.
# We can't assure when this exactly happens so we need a defer # We can't assure when this exactly happens so we need a defer
@ -174,14 +206,28 @@ class KanbanController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi
return promise return promise
loadUserStoriesForStatus: (ctx, statusId) -> loadUserStoriesForStatus: (ctx, statusId) ->
params = { status: statusId } filteredStatus = @location.search().status
# if there are filters applied the action doesn't end if the statusId is not in the url
if filteredStatus
filteredStatus = filteredStatus.split(",").map (it) -> parseInt(it, 10)
return if filteredStatus.indexOf(statusId) == -1
params = {
status: statusId
include_attachments: true,
include_tasks: true
}
params = _.merge params, @location.search()
return @rs.userstories.listAll(@scope.projectId, params).then (userstories) => return @rs.userstories.listAll(@scope.projectId, params).then (userstories) =>
@scope.usByStatus[statusId] = _.sortBy(userstories, "kanban_order")
@scope.$broadcast("kanban:shown-userstories-for-status", statusId, userstories) @scope.$broadcast("kanban:shown-userstories-for-status", statusId, userstories)
return userstories return userstories
hideUserStoriesForStatus: (ctx, statusId) -> hideUserStoriesForStatus: (ctx, statusId) ->
@scope.usByStatus[statusId] = []
@scope.$broadcast("kanban:hidden-userstories-for-status", statusId) @scope.$broadcast("kanban:hidden-userstories-for-status", statusId)
loadKanban: -> loadKanban: ->
@ -193,7 +239,7 @@ class KanbanController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi
loadProject: -> loadProject: ->
return @rs.projects.getBySlug(@params.pslug).then (project) => return @rs.projects.getBySlug(@params.pslug).then (project) =>
if not project.is_kanban_activated if not project.is_kanban_activated
@location.path(@navUrls.resolve("permission-denied")) @errorHandlingService.permissionDenied()
@scope.projectId = project.id @scope.projectId = project.id
@scope.project = project @scope.project = project
@ -203,8 +249,6 @@ class KanbanController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi
@scope.usStatusById = groupBy(project.us_statuses, (x) -> x.id) @scope.usStatusById = groupBy(project.us_statuses, (x) -> x.id)
@scope.usStatusList = _.sortBy(project.us_statuses, "order") @scope.usStatusList = _.sortBy(project.us_statuses, "order")
@.generateStatusViewModes()
@scope.$emit("project:loaded", project) @scope.$emit("project:loaded", project)
return project return project
@ -219,82 +263,40 @@ class KanbanController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi
@.fillUsersAndRoles(project.members, project.roles) @.fillUsersAndRoles(project.members, project.roles)
@.initializeSubscription() @.initializeSubscription()
@.loadKanban() @.loadKanban()
@.generateFilters()
## View Mode methods
generateStatusViewModes: ->
storedStatusViewModes = @rs.kanban.getStatusViewModes(@scope.projectId)
@scope.statusViewModes = {}
for status in @scope.usStatusList
mode = storedStatusViewModes[status.id] || defaultViewMode
@scope.statusViewModes[status.id] = mode
@.storeStatusViewModes()
storeStatusViewModes: ->
@rs.kanban.storeStatusViewModes(@scope.projectId, @scope.statusViewModes)
updateStatusViewMode: (statusId, newViewMode) ->
@scope.statusViewModes[statusId] = newViewMode
@.storeStatusViewModes()
isMaximized: (statusId) ->
mode = @scope.statusViewModes[statusId] or defaultViewMode
return mode == 'maximized'
isMinimized: (statusId) ->
mode = @scope.statusViewModes[statusId] or defaultViewMode
return mode == 'minimized'
# Utils methods # Utils methods
prepareBulkUpdateData: (uses, field="kanban_order") -> prepareBulkUpdateData: (uses, field="kanban_order") ->
return _.map(uses, (x) -> {"us_id": x.id, "order": x[field]}) return _.map(uses, (x) -> {"us_id": x.id, "order": x[field]})
resortUserStories: (uses) ->
items = []
for item, index in uses
item.kanban_order = index
if item.isModified()
items.push(item)
return items
moveUs: (ctx, us, oldStatusId, newStatusId, index) -> moveUs: (ctx, us, oldStatusId, newStatusId, index) ->
if oldStatusId != newStatusId us = @kanbanUserstoriesService.getUsModel(us.get('id'))
# Remove us from old status column
r = @scope.usByStatus[oldStatusId].indexOf(us)
@scope.usByStatus[oldStatusId].splice(r, 1)
# Add us to new status column. moveUpdateData = @kanbanUserstoriesService.move(us.id, newStatusId, index)
@scope.usByStatus[newStatusId].splice(index, 0, us)
us.status = newStatusId
else
r = @scope.usByStatus[newStatusId].indexOf(us)
@scope.usByStatus[newStatusId].splice(r, 1)
@scope.usByStatus[newStatusId].splice(index, 0, us)
itemsToSave = @.resortUserStories(@scope.usByStatus[newStatusId]) params = {
@scope.usByStatus[newStatusId] = _.sortBy(@scope.usByStatus[newStatusId], "kanban_order") include_attachments: true,
include_tasks: true
}
# Persist the userstory options = {
promise = @repo.save(us) headers: {
"set-orders": JSON.stringify(moveUpdateData.set_orders)
}
}
# Rehash userstories order field promise = @repo.save(us, true, params, options, true)
# and persist in bulk all changes.
promise = promise.then =>
itemsToSave = _.reject(itemsToSave, {"id": us.id})
data = @.prepareBulkUpdateData(itemsToSave)
return @rs.userstories.bulkUpdateKanbanOrder(us.project, data).then => promise = promise.then (result) =>
return itemsToSave headers = result[1]
if headers && headers['taiga-info-order-updated']
order = JSON.parse(headers['taiga-info-order-updated'])
@kanbanUserstoriesService.assignOrders(order)
return promise return promise
module.controller("KanbanController", KanbanController) module.controller("KanbanController", KanbanController)
############################################################################# #############################################################################
@ -321,7 +323,7 @@ module.directive("tgKanban", ["$tgRepo", "$rootScope", KanbanDirective])
## Kanban Archived Status Column Header Control ## Kanban Archived Status Column Header Control
############################################################################# #############################################################################
KanbanArchivedStatusHeaderDirective = ($rootscope, $translate) -> KanbanArchivedStatusHeaderDirective = ($rootscope, $translate, kanbanUserstoriesService) ->
showArchivedText = $translate.instant("KANBAN.ACTION_SHOW_ARCHIVED") showArchivedText = $translate.instant("KANBAN.ACTION_SHOW_ARCHIVED")
hideArchivedText = $translate.instant("KANBAN.ACTION_HIDE_ARCHIVED") hideArchivedText = $translate.instant("KANBAN.ACTION_HIDE_ARCHIVED")
@ -329,6 +331,9 @@ KanbanArchivedStatusHeaderDirective = ($rootscope, $translate) ->
status = $scope.$eval($attrs.tgKanbanArchivedStatusHeader) status = $scope.$eval($attrs.tgKanbanArchivedStatusHeader)
hidden = true hidden = true
kanbanUserstoriesService.addArchivedStatus(status.id)
kanbanUserstoriesService.hideStatus(status.id)
$scope.class = "icon-watch" $scope.class = "icon-watch"
$scope.title = showArchivedText $scope.title = showArchivedText
@ -341,24 +346,27 @@ KanbanArchivedStatusHeaderDirective = ($rootscope, $translate) ->
$scope.title = showArchivedText $scope.title = showArchivedText
$rootscope.$broadcast("kanban:hide-userstories-for-status", status.id) $rootscope.$broadcast("kanban:hide-userstories-for-status", status.id)
kanbanUserstoriesService.hideStatus(status.id)
else else
$scope.class = "icon-unwatch" $scope.class = "icon-unwatch"
$scope.title = hideArchivedText $scope.title = hideArchivedText
$rootscope.$broadcast("kanban:show-userstories-for-status", status.id) $rootscope.$broadcast("kanban:show-userstories-for-status", status.id)
kanbanUserstoriesService.showStatus(status.id)
$scope.$on "$destroy", -> $scope.$on "$destroy", ->
$el.off() $el.off()
return {link:link} return {link:link}
module.directive("tgKanbanArchivedStatusHeader", [ "$rootScope", "$translate", KanbanArchivedStatusHeaderDirective]) module.directive("tgKanbanArchivedStatusHeader", [ "$rootScope", "$translate", "tgKanbanUserstories", KanbanArchivedStatusHeaderDirective])
############################################################################# #############################################################################
## Kanban Archived Status Column Intro Directive ## Kanban Archived Status Column Intro Directive
############################################################################# #############################################################################
KanbanArchivedStatusIntroDirective = ($translate) -> KanbanArchivedStatusIntroDirective = ($translate, kanbanUserstoriesService) ->
userStories = [] userStories = []
link = ($scope, $el, $attrs) -> link = ($scope, $el, $attrs) ->
@ -366,105 +374,40 @@ KanbanArchivedStatusIntroDirective = ($translate) ->
status = $scope.$eval($attrs.tgKanbanArchivedStatusIntro) status = $scope.$eval($attrs.tgKanbanArchivedStatusIntro)
$el.text(hiddenUserStoriexText) $el.text(hiddenUserStoriexText)
updateIntroText = -> updateIntroText = (hasArchived) ->
if userStories.length > 0 if hasArchived
$el.text("") $el.text("")
else else
$el.text(hiddenUserStoriexText) $el.text(hiddenUserStoriexText)
$scope.$on "kanban:us:move", (ctx, itemUs, oldStatusId, newStatusId, itemIndex) -> $scope.$on "kanban:us:move", (ctx, itemUs, oldStatusId, newStatusId, itemIndex) ->
# The destination columnd is this one hasArchived = !!kanbanUserstoriesService.getStatus(newStatusId).length
if status.id == newStatusId updateIntroText(hasArchived)
# Reorder
if status.id == oldStatusId
r = userStories.indexOf(itemUs)
userStories.splice(r, 1)
userStories.splice(itemIndex, 0, itemUs)
# Archiving user story
else
itemUs.isArchived = true
userStories.splice(itemIndex, 0, itemUs)
# Unarchiving user story
else if status.id == oldStatusId
itemUs.isArchived = false
r = userStories.indexOf(itemUs)
userStories.splice(r, 1)
updateIntroText()
$scope.$on "kanban:shown-userstories-for-status", (ctx, statusId, userStoriesLoaded) -> $scope.$on "kanban:shown-userstories-for-status", (ctx, statusId, userStoriesLoaded) ->
if statusId == status.id if statusId == status.id
userStories = _.filter(userStoriesLoaded, (us) -> us.status == status.id) kanbanUserstoriesService.deleteStatus(statusId)
updateIntroText() kanbanUserstoriesService.add(userStoriesLoaded)
hasArchived = !!kanbanUserstoriesService.getStatus(statusId).length
updateIntroText(hasArchived)
$scope.$on "kanban:hidden-userstories-for-status", (ctx, statusId) -> $scope.$on "kanban:hidden-userstories-for-status", (ctx, statusId) ->
if statusId == status.id if statusId == status.id
userStories = [] updateIntroText(false)
updateIntroText()
$scope.$on "$destroy", -> $scope.$on "$destroy", ->
$el.off() $el.off()
return {link:link} return {link:link}
module.directive("tgKanbanArchivedStatusIntro", ["$translate", KanbanArchivedStatusIntroDirective]) module.directive("tgKanbanArchivedStatusIntro", ["$translate", "tgKanbanUserstories", KanbanArchivedStatusIntroDirective])
#############################################################################
## Kanban User Story Directive
#############################################################################
KanbanUserstoryDirective = ($rootscope, $loading, $rs, $rs2) ->
link = ($scope, $el, $attrs, $model) ->
$scope.$watch "us", (us) ->
if us.is_blocked and not $el.hasClass("blocked")
$el.addClass("blocked")
else if not us.is_blocked and $el.hasClass("blocked")
$el.removeClass("blocked")
$el.on 'click', '.edit-us', (event) ->
if $el.find(".icon-edit").hasClass("noclick")
return
target = $(event.target)
currentLoading = $loading()
.target(target)
.timeout(200)
.removeClasses("icon-edit")
.start()
us = $model.$modelValue
$rs.userstories.getByRef(us.project, us.ref).then (editingUserStory) =>
$rs2.attachments.list("us", us.id, us.project).then (attachments) =>
$rootscope.$broadcast("usform:edit", editingUserStory, attachments.toJS())
currentLoading.finish()
$scope.getTemplateUrl = () ->
if $scope.us.isPlaceholder
return "common/components/kanban-placeholder.html"
else
return "kanban/kanban-task.html"
$scope.$on "$destroy", ->
$el.off()
return {
template: '<ng-include src="getTemplateUrl()"/>',
link: link
require: "ngModel"
}
module.directive("tgKanbanUserstory", ["$rootScope", "$tgLoading", "$tgResources", "tgResources", KanbanUserstoryDirective])
############################################################################# #############################################################################
## Kanban Squish Column Directive ## Kanban Squish Column Directive
############################################################################# #############################################################################
KanbanSquishColumnDirective = (rs) -> KanbanSquishColumnDirective = (rs) ->
link = ($scope, $el, $attrs) -> link = ($scope, $el, $attrs) ->
$scope.$on "project:loaded", (event, project) -> $scope.$on "project:loaded", (event, project) ->
$scope.folds = rs.kanban.getStatusColumnModes(project.id) $scope.folds = rs.kanban.getStatusColumnModes(project.id)
@ -484,6 +427,7 @@ KanbanSquishColumnDirective = (rs) ->
return 310 return 310
totalWidth = _.reduce columnWidths, (total, width) -> totalWidth = _.reduce columnWidths, (total, width) ->
return total + width return total + width
$el.find('.kanban-table-inner').css("width", totalWidth) $el.find('.kanban-table-inner').css("width", totalWidth)
return {link: link} return {link: link}
@ -501,7 +445,7 @@ KanbanWipLimitDirective = ->
redrawWipLimit = => redrawWipLimit = =>
$el.find(".kanban-wip-limit").remove() $el.find(".kanban-wip-limit").remove()
timeout 200, => timeout 200, =>
element = $el.find(".kanban-task")[status.wip_limit] element = $el.find("tg-card")[status.wip_limit]
if element if element
angular.element(element).before("<div class='kanban-wip-limit'></div>") angular.element(element).before("<div class='kanban-wip-limit'></div>")
@ -517,79 +461,3 @@ KanbanWipLimitDirective = ->
return {link: link} return {link: link}
module.directive("tgKanbanWipLimit", KanbanWipLimitDirective) module.directive("tgKanbanWipLimit", KanbanWipLimitDirective)
#############################################################################
## Kanban User Directive
#############################################################################
KanbanUserDirective = ($log, $compile, $translate) ->
template = _.template("""
<figure class="avatar">
<a href="#" title="{{'US.ASSIGN' | translate}}" <% if (!clickable) {%>class="not-clickable"<% } %>>
<img src="<%- imgurl %>" alt="<%- name %>" class="avatar">
</a>
</figure>
""")
clickable = false
link = ($scope, $el, $attrs, $model) ->
username_label = $el.parent().find("a.task-assigned")
username_label.addClass("not-clickable")
if not $attrs.tgKanbanUserAvatar
return $log.error "KanbanUserDirective: no attr is defined"
wtid = $scope.$watch $attrs.tgKanbanUserAvatar, (v) ->
if not $scope.usersById?
$log.error "KanbanUserDirective requires userById set in scope."
wtid()
else
user = $scope.usersById[v]
render(user)
render = (user) ->
if user is undefined
ctx = {
name: $translate.instant("COMMON.ASSIGNED_TO.NOT_ASSIGNED"),
imgurl: "/#{window._version}/images/unnamed.png",
clickable: clickable
}
else
ctx = {
name: user.full_name_display,
imgurl: user.photo,
clickable: clickable
}
html = $compile(template(ctx))($scope)
$el.html(html)
username_label.text(ctx.name)
bindOnce $scope, "project", (project) ->
if project.my_permissions.indexOf("modify_us") > -1
clickable = true
$el.on "click", (event) =>
if $el.find("a").hasClass("noclick")
return
us = $model.$modelValue
$ctrl = $el.controller()
$ctrl.changeUsAssignedTo(us)
username_label.removeClass("not-clickable")
username_label.on "click", (event) ->
if $el.find("a").hasClass("noclick")
return
us = $model.$modelValue
$ctrl = $el.controller()
$ctrl.changeUsAssignedTo(us)
$scope.$on "$destroy", ->
$el.off()
return {link: link, require:"ngModel"}
module.directive("tgKanbanUserAvatar", ["$log", "$compile", "$translate", KanbanUserDirective])

View File

@ -40,8 +40,12 @@ module = angular.module("taigaKanban")
KanbanSortableDirective = ($repo, $rs, $rootscope) -> KanbanSortableDirective = ($repo, $rs, $rootscope) ->
link = ($scope, $el, $attrs) -> link = ($scope, $el, $attrs) ->
bindOnce $scope, "project", (project) -> unwatch = $scope.$watch "usByStatus", (usByStatus) ->
if not (project.my_permissions.indexOf("modify_us") > -1) return if !usByStatus || !usByStatus.size
unwatch()
if not ($scope.project.my_permissions.indexOf("modify_us") > -1)
return return
oldParentScope = null oldParentScope = null
@ -63,7 +67,7 @@ KanbanSortableDirective = ($repo, $rs, $rootscope) ->
copy: false, copy: false,
mirrorContainer: tdom[0], mirrorContainer: tdom[0],
moves: (item) -> moves: (item) ->
return $(item).hasClass('kanban-task') return $(item).is('tg-card')
}) })
drake.on 'drag', (item) -> drake.on 'drag', (item) ->
@ -83,14 +87,14 @@ KanbanSortableDirective = ($repo, $rs, $rootscope) ->
deleteElement(itemEl) deleteElement(itemEl)
$scope.$apply -> $scope.$apply ->
$rootscope.$broadcast("kanban:us:move", itemUs, itemUs.status, newStatusId, itemIndex) $rootscope.$broadcast("kanban:us:move", itemUs, itemUs.getIn(['model', 'status']), newStatusId, itemIndex)
scroll = autoScroll(containers, { scroll = autoScroll(containers, {
margin: 20, margin: 100,
pixels: 30, pixels: 30,
scrollWhenOutside: true, scrollWhenOutside: true,
autoScroll: () -> autoScroll: () ->
return this.down && drake.dragging; return this.down && drake.dragging
}) })
$scope.$on "$destroy", -> $scope.$on "$destroy", ->

View File

@ -168,6 +168,8 @@ RelatedTaskCreateFormDirective = ($repo, $compile, $confirm, $tgmodel, $loading,
$scope.newTask = $tgmodel.make_model("tasks", newTask) $scope.newTask = $tgmodel.make_model("tasks", newTask)
render = -> render = ->
return if $scope.openNewRelatedTask
$scope.openNewRelatedTask = true $scope.openNewRelatedTask = true
$el.on "keyup", "input", (event)-> $el.on "keyup", "input", (event)->
@ -229,7 +231,7 @@ RelatedTasksDirective = ($repo, $rs, $rootscope) ->
link = ($scope, $el, $attrs) -> link = ($scope, $el, $attrs) ->
loadTasks = -> loadTasks = ->
return $rs.tasks.list($scope.projectId, null, $scope.usId).then (tasks) => return $rs.tasks.list($scope.projectId, null, $scope.usId).then (tasks) =>
$scope.tasks = _.sortBy(tasks, 'ref') $scope.tasks = _.sortBy(tasks, (x) => [x.us_order, x.ref])
return tasks return tasks
_isVisible = -> _isVisible = ->
@ -267,9 +269,9 @@ RelatedTasksDirective = ($repo, $rs, $rootscope) ->
module.directive("tgRelatedTasks", ["$tgRepo", "$tgResources", "$rootScope", RelatedTasksDirective]) module.directive("tgRelatedTasks", ["$tgRepo", "$tgResources", "$rootScope", RelatedTasksDirective])
RelatedTaskAssignedToInlineEditionDirective = ($repo, $rootscope, $translate) -> RelatedTaskAssignedToInlineEditionDirective = ($repo, $rootscope, $translate, avatarService) ->
template = _.template(""" template = _.template("""
<img src="<%- imgurl %>" alt="<%- name %>"/> <img style="background-color: <%- bg %>" src="<%- imgurl %>" alt="<%- name %>"/>
<figcaption><%- name %></figcaption> <figcaption><%- name %></figcaption>
""") """)
@ -277,11 +279,15 @@ RelatedTaskAssignedToInlineEditionDirective = ($repo, $rootscope, $translate) ->
updateRelatedTask = (task) -> updateRelatedTask = (task) ->
ctx = { ctx = {
name: $translate.instant("COMMON.ASSIGNED_TO.NOT_ASSIGNED"), name: $translate.instant("COMMON.ASSIGNED_TO.NOT_ASSIGNED"),
imgurl: "/" + window._version + "/images/unnamed.png"
} }
member = $scope.usersById[task.assigned_to] member = $scope.usersById[task.assigned_to]
avatar = avatarService.getAvatar(member)
ctx.imgurl = avatar.url
ctx.bg = avatar.bg
if member if member
ctx.imgurl = member.photo
ctx.name = member.full_name_display ctx.name = member.full_name_display
$el.find(".avatar").html(template(ctx)) $el.find(".avatar").html(template(ctx))
@ -320,5 +326,5 @@ RelatedTaskAssignedToInlineEditionDirective = ($repo, $rootscope, $translate) ->
return {link: link} return {link: link}
module.directive("tgRelatedTaskAssignedToInlineEdition", ["$tgRepo", "$rootScope", "$translate", module.directive("tgRelatedTaskAssignedToInlineEdition", ["$tgRepo", "$rootScope", "$translate", "tgAvatarService",
RelatedTaskAssignedToInlineEditionDirective]) RelatedTaskAssignedToInlineEditionDirective])

View File

@ -81,6 +81,7 @@ urls = {
"project-transfer-start": "/projects/%s/transfer_start" "project-transfer-start": "/projects/%s/transfer_start"
# Project Values - Choises # Project Values - Choises
"epic-statuses": "/epic-statuses"
"userstory-statuses": "/userstory-statuses" "userstory-statuses": "/userstory-statuses"
"points": "/points" "points": "/points"
"task-statuses": "/task-statuses" "task-statuses": "/task-statuses"
@ -92,11 +93,21 @@ urls = {
# Milestones/Sprints # Milestones/Sprints
"milestones": "/milestones" "milestones": "/milestones"
# Epics
"epics": "/epics"
"epic-upvote": "/epics/%s/upvote"
"epic-downvote": "/epics/%s/downvote"
"epic-watch": "/epics/%s/watch"
"epic-unwatch": "/epics/%s/unwatch"
"epic-related-userstories": "/epics/%s/related_userstories"
"epic-related-userstories-bulk-create": "/epics/%s/related_userstories/bulk_create"
# User stories # User stories
"userstories": "/userstories" "userstories": "/userstories"
"bulk-create-us": "/userstories/bulk_create" "bulk-create-us": "/userstories/bulk_create"
"bulk-update-us-backlog-order": "/userstories/bulk_update_backlog_order" "bulk-update-us-backlog-order": "/userstories/bulk_update_backlog_order"
"bulk-update-us-sprint-order": "/userstories/bulk_update_sprint_order" "bulk-update-us-milestone": "/userstories/bulk_update_milestone"
"bulk-update-us-miles-order": "/userstories/bulk_update_sprint_order"
"bulk-update-us-kanban-order": "/userstories/bulk_update_kanban_order" "bulk-update-us-kanban-order": "/userstories/bulk_update_kanban_order"
"userstories-filters": "/userstories/filters_data" "userstories-filters": "/userstories/filters_data"
"userstory-upvote": "/userstories/%s/upvote" "userstory-upvote": "/userstories/%s/upvote"
@ -112,6 +123,7 @@ urls = {
"task-downvote": "/tasks/%s/downvote" "task-downvote": "/tasks/%s/downvote"
"task-watch": "/tasks/%s/watch" "task-watch": "/tasks/%s/watch"
"task-unwatch": "/tasks/%s/unwatch" "task-unwatch": "/tasks/%s/unwatch"
"task-filters": "/tasks/filters_data"
# Issues # Issues
"issues": "/issues" "issues": "/issues"
@ -128,26 +140,30 @@ urls = {
"wiki-links": "/wiki-links" "wiki-links": "/wiki-links"
# History # History
"history/epic": "/history/epic"
"history/us": "/history/userstory" "history/us": "/history/userstory"
"history/issue": "/history/issue" "history/issue": "/history/issue"
"history/task": "/history/task" "history/task": "/history/task"
"history/wiki": "/history/wiki" "history/wiki": "/history/wiki/%s"
# Attachments # Attachments
"attachments/epic": "/epics/attachments"
"attachments/us": "/userstories/attachments" "attachments/us": "/userstories/attachments"
"attachments/issue": "/issues/attachments" "attachments/issue": "/issues/attachments"
"attachments/task": "/tasks/attachments" "attachments/task": "/tasks/attachments"
"attachments/wiki_page": "/wiki/attachments" "attachments/wiki_page": "/wiki/attachments"
# Custom Attributess # Custom Attributess
"custom-attributes/epic": "/epic-custom-attributes"
"custom-attributes/userstory": "/userstory-custom-attributes" "custom-attributes/userstory": "/userstory-custom-attributes"
"custom-attributes/issue": "/issue-custom-attributes"
"custom-attributes/task": "/task-custom-attributes" "custom-attributes/task": "/task-custom-attributes"
"custom-attributes/issue": "/issue-custom-attributes"
# Custom Attributess - Values # Custom Attributess - Values
"custom-attributes-values/epic": "/epics/custom-attributes-values"
"custom-attributes-values/userstory": "/userstories/custom-attributes-values" "custom-attributes-values/userstory": "/userstories/custom-attributes-values"
"custom-attributes-values/issue": "/issues/custom-attributes-values"
"custom-attributes-values/task": "/tasks/custom-attributes-values" "custom-attributes-values/task": "/tasks/custom-attributes-values"
"custom-attributes-values/issue": "/issues/custom-attributes-values"
# Webhooks # Webhooks
"webhooks": "/webhooks" "webhooks": "/webhooks"
@ -156,6 +172,7 @@ urls = {
"webhooklogs-resend": "/webhooklogs/%s/resend" "webhooklogs-resend": "/webhooklogs/%s/resend"
# Reports - CSV # Reports - CSV
"epics-csv": "/epics/csv?uuid=%s"
"userstories-csv": "/userstories/csv?uuid=%s" "userstories-csv": "/userstories/csv?uuid=%s"
"tasks-csv": "/tasks/csv?uuid=%s" "tasks-csv": "/tasks/csv?uuid=%s"
"issues-csv": "/issues/csv?uuid=%s" "issues-csv": "/issues/csv?uuid=%s"
@ -217,6 +234,7 @@ module.run([
"$tgRolesResourcesProvider", "$tgRolesResourcesProvider",
"$tgUserSettingsResourcesProvider", "$tgUserSettingsResourcesProvider",
"$tgSprintsResourcesProvider", "$tgSprintsResourcesProvider",
"$tgEpicsResourcesProvider",
"$tgUserstoriesResourcesProvider", "$tgUserstoriesResourcesProvider",
"$tgTasksResourcesProvider", "$tgTasksResourcesProvider",
"$tgIssuesResourcesProvider", "$tgIssuesResourcesProvider",

View File

@ -29,6 +29,9 @@ resourceProvider = ($repo) ->
return $repo.queryOne(resource, objectId) return $repo.queryOne(resource, objectId)
service = { service = {
epic: {
get: (objectId) -> _get(objectId, "custom-attributes-values/epic")
}
userstory: { userstory: {
get: (objectId) -> _get(objectId, "custom-attributes-values/userstory") get: (objectId) -> _get(objectId, "custom-attributes-values/userstory")
} }

View File

@ -32,6 +32,9 @@ resourceProvider = ($repo) ->
return $repo.queryMany(resource, {project: projectId}) return $repo.queryMany(resource, {project: projectId})
service = { service = {
epic:{
list: (projectId) -> _list(projectId, "custom-attributes/epic")
}
userstory:{ userstory:{
list: (projectId) -> _list(projectId, "custom-attributes/userstory") list: (projectId) -> _list(projectId, "custom-attributes/userstory")
} }

View File

@ -0,0 +1,77 @@
###
# Copyright (C) 2014-2016 Andrey Antukh <niwi@niwi.nz>
# Copyright (C) 2014-2016 Jesús Espino Garcia <jespinog@gmail.com>
# Copyright (C) 2014-2016 David Barragán Merino <bameda@dbarragan.com>
# Copyright (C) 2014-2016 Alejandro Alonso <alejandro.alonso@kaleidos.net>
# Copyright (C) 2014-2016 Juan Francisco Alcántara <juanfran.alcantara@kaleidos.net>
# Copyright (C) 2014-2016 Xavi Julian <xavier.julian@kaleidos.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# File: modules/resources/epics.coffee
###
taiga = @.taiga
generateHash = taiga.generateHash
resourceProvider = ($repo, $http, $urls, $storage) ->
service = {}
hashSuffix = "epics-queryparams"
service.getByRef = (projectId, ref) ->
params = service.getQueryParams(projectId)
params.project = projectId
params.ref = ref
return $repo.queryOne("epics", "by_ref", params)
service.listValues = (projectId, type) ->
params = {"project": projectId}
service.storeQueryParams(projectId, params)
return $repo.queryMany(type, params)
service.storeQueryParams = (projectId, params) ->
ns = "#{projectId}:#{hashSuffix}"
hash = generateHash([projectId, ns])
$storage.set(hash, params)
service.getQueryParams = (projectId) ->
ns = "#{projectId}:#{hashSuffix}"
hash = generateHash([projectId, ns])
return $storage.get(hash) or {}
service.upvote = (epicId) ->
url = $urls.resolve("epic-upvote", epicId)
return $http.post(url)
service.downvote = (epicId) ->
url = $urls.resolve("epic-downvote", epicId)
return $http.post(url)
service.watch = (epicId) ->
url = $urls.resolve("epic-watch", epicId)
return $http.post(url)
service.unwatch = (epicId) ->
url = $urls.resolve("epic-unwatch", epicId)
return $http.post(url)
return (instance) ->
instance.epics = service
module = angular.module("taigaResources")
module.factory("$tgEpicsResourcesProvider", ["$tgRepo","$tgHttp", "$tgUrls", "$tgStorage", resourceProvider])

View File

@ -31,6 +31,25 @@ resourceProvider = ($repo, $http, $urls) ->
service.get = (type, objectId) -> service.get = (type, objectId) ->
return $repo.queryOneRaw("history/#{type}", objectId) return $repo.queryOneRaw("history/#{type}", objectId)
service.editComment = (type, objectId, activityId, comment) ->
url = $urls.resolve("history/#{type}")
url = "#{url}/#{objectId}/edit_comment"
params = {
id: activityId
}
commentData = {
comment: comment
}
return $http.post(url, commentData, params).then (data) =>
return data.data
service.getCommentHistory = (type, objectId, activityId) ->
url = $urls.resolve("history/#{type}")
url = "#{url}/#{objectId}/comment_versions"
params = {id: activityId}
return $http.get(url, params).then (data) =>
return data.data
service.deleteComment = (type, objectId, activityId) -> service.deleteComment = (type, objectId, activityId) ->
url = $urls.resolve("history/#{type}") url = $urls.resolve("history/#{type}")
url = "#{url}/#{objectId}/delete_comment" url = "#{url}/#{objectId}/delete_comment"

View File

@ -30,8 +30,6 @@ generateHash = taiga.generateHash
resourceProvider = ($repo, $http, $urls, $storage, $q) -> resourceProvider = ($repo, $http, $urls, $storage, $q) ->
service = {} service = {}
hashSuffix = "issues-queryparams" hashSuffix = "issues-queryparams"
filtersHashSuffix = "issues-filters"
myFiltersHashSuffix = "issues-my-filters"
service.get = (projectId, issueId) -> service.get = (projectId, issueId) ->
params = service.getQueryParams(projectId) params = service.getQueryParams(projectId)
@ -95,53 +93,6 @@ resourceProvider = ($repo, $http, $urls, $storage, $q) ->
hash = generateHash([projectId, ns]) hash = generateHash([projectId, ns])
return $storage.get(hash) or {} return $storage.get(hash) or {}
service.storeFilters = (projectSlug, params) ->
ns = "#{projectSlug}:#{filtersHashSuffix}"
hash = generateHash([projectSlug, ns])
$storage.set(hash, params)
service.getFilters = (projectSlug) ->
ns = "#{projectSlug}:#{filtersHashSuffix}"
hash = generateHash([projectSlug, ns])
return $storage.get(hash) or {}
service.storeMyFilters = (projectId, myFilters) ->
deferred = $q.defer()
url = $urls.resolve("user-storage")
ns = "#{projectId}:#{myFiltersHashSuffix}"
hash = generateHash([projectId, ns])
if _.isEmpty(myFilters)
promise = $http.delete("#{url}/#{hash}", {key: hash, value:myFilters})
promise.then ->
deferred.resolve()
promise.then null, ->
deferred.reject()
else
promise = $http.put("#{url}/#{hash}", {key: hash, value:myFilters})
promise.then (data) ->
deferred.resolve()
promise.then null, (data) ->
innerPromise = $http.post("#{url}", {key: hash, value:myFilters})
innerPromise.then ->
deferred.resolve()
innerPromise.then null, ->
deferred.reject()
return deferred.promise
service.getMyFilters = (projectId) ->
deferred = $q.defer()
url = $urls.resolve("user-storage")
ns = "#{projectId}:#{myFiltersHashSuffix}"
hash = generateHash([projectId, ns])
promise = $http.get("#{url}/#{hash}")
promise.then (data) ->
deferred.resolve(data.data.value)
promise.then null, (data) ->
deferred.resolve({})
return deferred.promise
return (instance) -> return (instance) ->
instance.issues = service instance.issues = service

View File

@ -32,16 +32,6 @@ resourceProvider = ($storage) ->
hashSuffixStatusViewModes = "kanban-statusviewmodels" hashSuffixStatusViewModes = "kanban-statusviewmodels"
hashSuffixStatusColumnModes = "kanban-statuscolumnmodels" hashSuffixStatusColumnModes = "kanban-statuscolumnmodels"
service.storeStatusViewModes = (projectId, params) ->
ns = "#{projectId}:#{hashSuffixStatusViewModes}"
hash = generateHash([projectId, ns])
$storage.set(hash, params)
service.getStatusViewModes = (projectId) ->
ns = "#{projectId}:#{hashSuffixStatusViewModes}"
hash = generateHash([projectId, ns])
return $storage.get(hash) or {}
service.storeStatusColumnModes = (projectId, params) -> service.storeStatusColumnModes = (projectId, params) ->
ns = "#{projectId}:#{hashSuffixStatusColumnModes}" ns = "#{projectId}:#{hashSuffixStatusColumnModes}"
hash = generateHash([projectId, ns]) hash = generateHash([projectId, ns])

View File

@ -40,7 +40,7 @@ resourceProvider = ($config, $repo, $http, $urls, $auth, $q, $translate) ->
return $repo.queryMany("projects") return $repo.queryMany("projects")
service.listByMember = (memberId) -> service.listByMember = (memberId) ->
params = {"member": memberId, "order_by": "memberships__user_order"} params = {"member": memberId, "order_by": "user_order"}
return $repo.queryMany("projects", params) return $repo.queryMany("projects", params)
service.templates = -> service.templates = ->
@ -61,18 +61,22 @@ resourceProvider = ($config, $repo, $http, $urls, $auth, $q, $translate) ->
url = $urls.resolve("bulk-update-projects-order") url = $urls.resolve("bulk-update-projects-order")
return $http.post(url, bulkData) return $http.post(url, bulkData)
service.regenerate_epics_csv_uuid = (projectId) ->
url = "#{$urls.resolve("projects")}/#{projectId}/regenerate_epics_csv_uuid"
return $http.post(url)
service.regenerate_userstories_csv_uuid = (projectId) -> service.regenerate_userstories_csv_uuid = (projectId) ->
url = "#{$urls.resolve("projects")}/#{projectId}/regenerate_userstories_csv_uuid" url = "#{$urls.resolve("projects")}/#{projectId}/regenerate_userstories_csv_uuid"
return $http.post(url) return $http.post(url)
service.regenerate_issues_csv_uuid = (projectId) ->
url = "#{$urls.resolve("projects")}/#{projectId}/regenerate_issues_csv_uuid"
return $http.post(url)
service.regenerate_tasks_csv_uuid = (projectId) -> service.regenerate_tasks_csv_uuid = (projectId) ->
url = "#{$urls.resolve("projects")}/#{projectId}/regenerate_tasks_csv_uuid" url = "#{$urls.resolve("projects")}/#{projectId}/regenerate_tasks_csv_uuid"
return $http.post(url) return $http.post(url)
service.regenerate_issues_csv_uuid = (projectId) ->
url = "#{$urls.resolve("projects")}/#{projectId}/regenerate_issues_csv_uuid"
return $http.post(url)
service.leave = (projectId) -> service.leave = (projectId) ->
url = "#{$urls.resolve("projects")}/#{projectId}/leave" url = "#{$urls.resolve("projects")}/#{projectId}/leave"
return $http.post(url) return $http.post(url)
@ -83,6 +87,34 @@ resourceProvider = ($config, $repo, $http, $urls, $auth, $q, $translate) ->
service.tagsColors = (projectId) -> service.tagsColors = (projectId) ->
return $repo.queryOne("projects", "#{projectId}/tags_colors") return $repo.queryOne("projects", "#{projectId}/tags_colors")
service.deleteTag = (projectId, tag) ->
url = "#{$urls.resolve("projects")}/#{projectId}/delete_tag"
return $http.post(url, {tag: tag})
service.createTag = (projectId, tag, color) ->
url = "#{$urls.resolve("projects")}/#{projectId}/create_tag"
data = {}
data.tag = tag
data.color = null
if color
data.color = color
return $http.post(url, data)
service.editTag = (projectId, from_tag, to_tag, color) ->
url = "#{$urls.resolve("projects")}/#{projectId}/edit_tag"
data = {}
data.from_tag = from_tag
if to_tag
data.to_tag = to_tag
data.color = null
if color
data.color = color
return $http.post(url, data)
service.mixTags = (projectId, to_tag, from_tags) ->
url = "#{$urls.resolve("projects")}/#{projectId}/mix_tags"
return $http.post(url, {to_tag: to_tag, from_tags: from_tags})
service.export = (projectId) -> service.export = (projectId) ->
url = "#{$urls.resolve("exporter")}/#{projectId}" url = "#{$urls.resolve("exporter")}/#{projectId}"
return $http.get(url) return $http.get(url)

View File

@ -38,17 +38,23 @@ resourceProvider = ($repo, $http, $urls, $storage) ->
params.project = projectId params.project = projectId
return $repo.queryOne("tasks", taskId, params) return $repo.queryOne("tasks", taskId, params)
service.getByRef = (projectId, ref) -> service.getByRef = (projectId, ref, extraParams) ->
params = service.getQueryParams(projectId) params = service.getQueryParams(projectId)
params.project = projectId params.project = projectId
params.ref = ref params.ref = ref
params = _.extend({}, params, extraParams)
return $repo.queryOne("tasks", "by_ref", params) return $repo.queryOne("tasks", "by_ref", params)
service.listInAllProjects = (filters) -> service.listInAllProjects = (filters) ->
return $repo.queryMany("tasks", filters) return $repo.queryMany("tasks", filters)
service.list = (projectId, sprintId=null, userStoryId=null) -> service.filtersData = (params) ->
params = {project: projectId} return $repo.queryOneRaw("task-filters", null, params)
service.list = (projectId, sprintId=null, userStoryId=null, params) ->
params = _.merge(params, {project: projectId})
params.milestone = sprintId if sprintId params.milestone = sprintId if sprintId
params.user_story = userStoryId if userStoryId params.user_story = userStoryId if userStoryId
service.storeQueryParams(projectId, params) service.storeQueryParams(projectId, params)
@ -56,7 +62,7 @@ resourceProvider = ($repo, $http, $urls, $storage) ->
service.bulkCreate = (projectId, sprintId, usId, data) -> service.bulkCreate = (projectId, sprintId, usId, data) ->
url = $urls.resolve("bulk-create-tasks") url = $urls.resolve("bulk-create-tasks")
params = {project_id: projectId, sprint_id: sprintId, us_id: usId, bulk_tasks: data} params = {project_id: projectId, milestone_id: sprintId, us_id: usId, bulk_tasks: data}
return $http.post(url, params).then (result) -> return $http.post(url, params).then (result) ->
return result.data return result.data

View File

@ -26,7 +26,7 @@ taiga = @.taiga
generateHash = taiga.generateHash generateHash = taiga.generateHash
resourceProvider = ($repo, $http, $urls, $storage) -> resourceProvider = ($repo, $http, $urls, $storage, $q) ->
service = {} service = {}
hashSuffix = "userstories-queryparams" hashSuffix = "userstories-queryparams"
@ -35,10 +35,12 @@ resourceProvider = ($repo, $http, $urls, $storage) ->
params.project = projectId params.project = projectId
return $repo.queryOne("userstories", usId, params) return $repo.queryOne("userstories", usId, params)
service.getByRef = (projectId, ref) -> service.getByRef = (projectId, ref, extraParams = {}) ->
params = service.getQueryParams(projectId) params = service.getQueryParams(projectId)
params.project = projectId params.project = projectId
params.ref = ref params.ref = ref
params = _.extend({}, params, extraParams)
return $repo.queryOne("userstories", "by_ref", params) return $repo.queryOne("userstories", "by_ref", params)
service.listInAllProjects = (filters) -> service.listInAllProjects = (filters) ->
@ -96,9 +98,9 @@ resourceProvider = ($repo, $http, $urls, $storage) ->
params = {project_id: projectId, bulk_stories: data} params = {project_id: projectId, bulk_stories: data}
return $http.post(url, params) return $http.post(url, params)
service.bulkUpdateSprintOrder = (projectId, data) -> service.bulkUpdateMilestone = (projectId, milestoneId, data) ->
url = $urls.resolve("bulk-update-us-sprint-order") url = $urls.resolve("bulk-update-us-milestone")
params = {project_id: projectId, bulk_stories: data} params = {project_id: projectId, milestone_id: milestoneId, bulk_stories: data}
return $http.post(url, params) return $http.post(url, params)
service.bulkUpdateKanbanOrder = (projectId, data) -> service.bulkUpdateKanbanOrder = (projectId, data) ->
@ -133,4 +135,4 @@ resourceProvider = ($repo, $http, $urls, $storage) ->
instance.userstories = service instance.userstories = service
module = angular.module("taigaResources") module = angular.module("taigaResources")
module.factory("$tgUserstoriesResourcesProvider", ["$tgRepo", "$tgHttp", "$tgUrls", "$tgStorage", resourceProvider]) module.factory("$tgUserstoriesResourcesProvider", ["$tgRepo", "$tgHttp", "$tgUrls", "$tgStorage", "$q", resourceProvider])

View File

@ -34,6 +34,9 @@ resourceProvider = ($repo, $http, $urls) ->
service.getBySlug = (projectId, slug) -> service.getBySlug = (projectId, slug) ->
return $repo.queryOne("wiki", "by_slug?project=#{projectId}&slug=#{slug}") return $repo.queryOne("wiki", "by_slug?project=#{projectId}&slug=#{slug}")
service.list = (projectId) ->
return $repo.queryMany("wiki", {project: projectId})
service.listLinks = (projectId) -> service.listLinks = (projectId) ->
return $repo.queryMany("wiki-links", {project: projectId}) return $repo.queryMany("wiki-links", {project: projectId})

View File

@ -48,10 +48,11 @@ class SearchController extends mixOf(taiga.Controller, taiga.PageMixin)
"$tgLocation", "$tgLocation",
"tgAppMetaService", "tgAppMetaService",
"$tgNavUrls", "$tgNavUrls",
"$translate" "$translate",
"tgErrorHandlingService"
] ]
constructor: (@scope, @repo, @rs, @params, @q, @location, @appMetaService, @navUrls, @translate) -> constructor: (@scope, @repo, @rs, @params, @q, @location, @appMetaService, @navUrls, @translate, @errorHandlingService) ->
@scope.sectionName = "Search" @scope.sectionName = "Search"
promise = @.loadInitialData() promise = @.loadInitialData()
@ -87,6 +88,8 @@ class SearchController extends mixOf(taiga.Controller, taiga.PageMixin)
return @rs.projects.getBySlug(@params.pslug).then (project) => return @rs.projects.getBySlug(@params.pslug).then (project) =>
@scope.project = project @scope.project = project
@scope.$emit('project:loaded', project) @scope.$emit('project:loaded', project)
@scope.epicStatusById = groupBy(project.epic_statuses, (x) -> x.id)
@scope.issueStatusById = groupBy(project.issue_statuses, (x) -> x.id) @scope.issueStatusById = groupBy(project.issue_statuses, (x) -> x.id)
@scope.taskStatusById = groupBy(project.task_statuses, (x) -> x.id) @scope.taskStatusById = groupBy(project.task_statuses, (x) -> x.id)
@scope.severityById = groupBy(project.severities, (x) -> x.id) @scope.severityById = groupBy(project.severities, (x) -> x.id)
@ -193,7 +196,7 @@ SearchDirective = ($log, $compile, $templatecache, $routeparams, $location) ->
return selectedSection return selectedSection
if data if data
for name in ["userstories", "issues", "tasks", "wikipages"] for name in ["userstories", "epics", "issues", "tasks", "wikipages"]
value = data[name] value = data[name]
if value.length > maxVal if value.length > maxVal
@ -221,6 +224,7 @@ SearchDirective = ($log, $compile, $templatecache, $routeparams, $location) ->
activeSectionName = section.name activeSectionName = section.name
templates = { templates = {
epics: $templatecache.get("search-epics")
issues: $templatecache.get("search-issues") issues: $templatecache.get("search-issues")
tasks: $templatecache.get("search-tasks") tasks: $templatecache.get("search-tasks")
userstories: $templatecache.get("search-userstories") userstories: $templatecache.get("search-userstories")

View File

@ -25,6 +25,7 @@
taiga = @.taiga taiga = @.taiga
bindOnce = @.taiga.bindOnce bindOnce = @.taiga.bindOnce
debounce = @.taiga.debounce debounce = @.taiga.debounce
trim = @.taiga.trim
CreateEditTaskDirective = ($repo, $model, $rs, $rootscope, $loading, lightboxService, $translate, $q, attachmentsService) -> CreateEditTaskDirective = ($repo, $model, $rs, $rootscope, $loading, lightboxService, $translate, $q, attachmentsService) ->
link = ($scope, $el, attrs) -> link = ($scope, $el, attrs) ->
@ -41,7 +42,8 @@ CreateEditTaskDirective = ($repo, $model, $rs, $rootscope, $loading, lightboxSer
attachmentsToAdd = attachmentsToAdd.push(attachment) attachmentsToAdd = attachmentsToAdd.push(attachment)
$scope.deleteAttachment = (attachment) -> $scope.deleteAttachment = (attachment) ->
attachmentsToDelete = attachmentsToDelete.push(attachment) if attachment.get("id")
attachmentsToDelete = attachmentsToDelete.push(attachment)
createAttachments = (obj) -> createAttachments = (obj) ->
promises = _.map attachmentsToAdd.toJS(), (attachment) -> promises = _.map attachmentsToAdd.toJS(), (attachment) ->
@ -55,6 +57,45 @@ CreateEditTaskDirective = ($repo, $model, $rs, $rootscope, $loading, lightboxSer
return $q.all(promises) return $q.all(promises)
tagsToAdd = []
$scope.addTag = (tag, color) ->
value = trim(tag.toLowerCase())
tags = $scope.project.tags
projectTags = $scope.project.tags_colors
tags = [] if not tags?
projectTags = {} if not projectTags?
if value not in tags
tags.push(value)
projectTags[tag] = color || null
$scope.project.tags = tags
itemtags = _.clone($scope.task.tags)
inserted = _.find itemtags, (it) -> it[0] == value
if !inserted
itemtags.push([tag , color])
$scope.task.tags = itemtags
$scope.deleteTag = (tag) ->
value = trim(tag[0].toLowerCase())
tags = $scope.project.tags
itemtags = _.clone($scope.task.tags)
_.remove itemtags, (tag) -> tag[0] == value
$scope.task.tags = itemtags
_.pull($scope.task.tags, value)
$scope.$on "taskform:new", (ctx, sprintId, usId) -> $scope.$on "taskform:new", (ctx, sprintId, usId) ->
$scope.task = { $scope.task = {
project: $scope.projectId project: $scope.projectId
@ -78,7 +119,10 @@ CreateEditTaskDirective = ($repo, $model, $rs, $rootscope, $loading, lightboxSer
$el.find(".title").html(newTask + " ") $el.find(".title").html(newTask + " ")
$el.find(".tag-input").val("") $el.find(".tag-input").val("")
lightboxService.open($el) lightboxService.open $el, () ->
$scope.createEditTaskOpen = false
$scope.createEditTaskOpen = true
$scope.$on "taskform:edit", (ctx, task, attachments) -> $scope.$on "taskform:edit", (ctx, task, attachments) ->
$scope.task = task $scope.task = task
@ -96,7 +140,10 @@ CreateEditTaskDirective = ($repo, $model, $rs, $rootscope, $loading, lightboxSer
$el.find(".title").html(edit + " ") $el.find(".title").html(edit + " ")
$el.find(".tag-input").val("") $el.find(".tag-input").val("")
lightboxService.open($el) lightboxService.open $el, () ->
$scope.createEditTaskOpen = false
$scope.createEditTaskOpen = true
submitButton = $el.find(".submit-button") submitButton = $el.find(".submit-button")
@ -108,6 +155,11 @@ CreateEditTaskDirective = ($repo, $model, $rs, $rootscope, $loading, lightboxSer
if not form.validate() if not form.validate()
return return
params = {
include_attachments: true,
include_tasks: true
}
if $scope.isNew if $scope.isNew
promise = $repo.create("tasks", $scope.task) promise = $repo.create("tasks", $scope.task)
broadcastEvent = "taskform:new:success" broadcastEvent = "taskform:new:success"
@ -116,20 +168,22 @@ CreateEditTaskDirective = ($repo, $model, $rs, $rootscope, $loading, lightboxSer
broadcastEvent = "taskform:edit:success" broadcastEvent = "taskform:edit:success"
promise.then (data) -> promise.then (data) ->
createAttachments(data)
deleteAttachments(data) deleteAttachments(data)
.then () => createAttachments(data)
.then () =>
currentLoading.finish()
lightboxService.close($el)
return data $rs.tasks.getByRef(data.project, data.ref, params).then (task) ->
$rootscope.$broadcast(broadcastEvent, task)
currentLoading = $loading() currentLoading = $loading()
.target(submitButton) .target(submitButton)
.start() .start()
# FIXME: error handling?
promise.then (data) -> promise.then (data) ->
currentLoading.finish() currentLoading.finish()
lightboxService.close($el) lightboxService.close($el)
$rootscope.$broadcast(broadcastEvent, data)
$el.on "submit", "form", submit $el.on "submit", "form", submit
@ -139,7 +193,7 @@ CreateEditTaskDirective = ($repo, $model, $rs, $rootscope, $loading, lightboxSer
return {link: link} return {link: link}
CreateBulkTasksDirective = ($repo, $rs, $rootscope, $loading, lightboxService) -> CreateBulkTasksDirective = ($repo, $rs, $rootscope, $loading, lightboxService, $model) ->
link = ($scope, $el, attrs) -> link = ($scope, $el, attrs) ->
$scope.form = {data: "", usId: null} $scope.form = {data: "", usId: null}
@ -161,6 +215,7 @@ CreateBulkTasksDirective = ($repo, $rs, $rootscope, $loading, lightboxService) -
promise = $rs.tasks.bulkCreate(projectId, sprintId, usId, data) promise = $rs.tasks.bulkCreate(projectId, sprintId, usId, data)
promise.then (result) -> promise.then (result) ->
result = _.map(result, (x) => $model.make_model('userstories', x))
currentLoading.finish() currentLoading.finish()
$rootscope.$broadcast("taskform:bulk:success", result) $rootscope.$broadcast("taskform:bulk:success", result)
lightboxService.close($el) lightboxService.close($el)
@ -205,5 +260,6 @@ module.directive("tgLbCreateBulkTasks", [
"$rootScope", "$rootScope",
"$tgLoading", "$tgLoading",
"lightboxService", "lightboxService",
"$tgModel",
CreateBulkTasksDirective CreateBulkTasksDirective
]) ])

View File

@ -38,13 +38,14 @@ module = angular.module("taigaTaskboard")
## Taskboard Controller ## Taskboard Controller
############################################################################# #############################################################################
class TaskboardController extends mixOf(taiga.Controller, taiga.PageMixin) class TaskboardController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.FiltersMixin)
@.$inject = [ @.$inject = [
"$scope", "$scope",
"$rootScope", "$rootScope",
"$tgRepo", "$tgRepo",
"$tgConfirm", "$tgConfirm",
"$tgResources", "$tgResources",
"tgResources"
"$routeParams", "$routeParams",
"$q", "$q",
"tgAppMetaService", "tgAppMetaService",
@ -52,12 +53,21 @@ class TaskboardController extends mixOf(taiga.Controller, taiga.PageMixin)
"$tgNavUrls" "$tgNavUrls"
"$tgEvents" "$tgEvents"
"$tgAnalytics", "$tgAnalytics",
"$translate" "$translate",
"tgErrorHandlingService",
"tgTaskboardTasks",
"$tgStorage",
"tgFilterRemoteStorageService"
] ]
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @appMetaService, @location, @navUrls, constructor: (@scope, @rootscope, @repo, @confirm, @rs, @rs2, @params, @q, @appMetaService, @location, @navUrls,
@events, @analytics, @translate) -> @events, @analytics, @translate, @errorHandlingService, @taskboardTasksService, @storage, @filterRemoteStorageService) ->
bindMethods(@) bindMethods(@)
@taskboardTasksService.reset()
@scope.userstories = []
@.openFilter = false
return if @.applyStoredFilters(@params.pslug, "tasks-filters")
@scope.sectionName = @translate.instant("TASKBOARD.SECTION_NAME") @scope.sectionName = @translate.instant("TASKBOARD.SECTION_NAME")
@.initializeEventHandlers() @.initializeEventHandlers()
@ -69,6 +79,155 @@ class TaskboardController extends mixOf(taiga.Controller, taiga.PageMixin)
# On Error # On Error
promise.then null, @.onInitialDataError.bind(@) promise.then null, @.onInitialDataError.bind(@)
taiga.defineImmutableProperty @.scope, "usTasks", () =>
return @taskboardTasksService.usTasks
setZoom: (zoomLevel, zoom) ->
if @.zoomLevel != zoomLevel
@taskboardTasksService.resetFolds()
@.zoomLevel = zoomLevel
@.zoom = zoom
if @.zoomLevel == '0'
@rootscope.$broadcast("sprint:zoom0")
changeQ: (q) ->
@.replaceFilter("q", q)
@.loadTasks()
@.generateFilters()
removeFilter: (filter) ->
@.unselectFilter(filter.dataType, filter.id)
@.loadTasks()
@.generateFilters()
addFilter: (newFilter) ->
@.selectFilter(newFilter.category.dataType, newFilter.filter.id)
@.loadTasks()
@.generateFilters()
selectCustomFilter: (customFilter) ->
@.replaceAllFilters(customFilter.filter)
@.loadTasks()
@.generateFilters()
removeCustomFilter: (customFilter) ->
@filterRemoteStorageService.getFilters(@scope.projectId, 'tasks-custom-filters').then (userFilters) =>
delete userFilters[customFilter.id]
@filterRemoteStorageService.storeFilters(@scope.projectId, userFilters, 'tasks-custom-filters').then(@.generateFilters)
saveCustomFilter: (name) ->
filters = {}
urlfilters = @location.search()
filters.tags = urlfilters.tags
filters.status = urlfilters.status
filters.assigned_to = urlfilters.assigned_to
filters.owner = urlfilters.owner
@filterRemoteStorageService.getFilters(@scope.projectId, 'tasks-custom-filters').then (userFilters) =>
userFilters[name] = filters
@filterRemoteStorageService.storeFilters(@scope.projectId, userFilters, 'tasks-custom-filters').then(@.generateFilters)
generateFilters: ->
@.storeFilters(@params.pslug, @location.search(), "tasks-filters")
urlfilters = @location.search()
loadFilters = {}
loadFilters.project = @scope.projectId
loadFilters.milestone = @scope.sprintId
loadFilters.tags = urlfilters.tags
loadFilters.status = urlfilters.status
loadFilters.assigned_to = urlfilters.assigned_to
loadFilters.owner = urlfilters.owner
loadFilters.q = urlfilters.q
return @q.all([
@rs.tasks.filtersData(loadFilters),
@filterRemoteStorageService.getFilters(@scope.projectId, 'tasks-custom-filters')
]).then (result) =>
data = result[0]
customFiltersRaw = result[1]
statuses = _.map data.statuses, (it) ->
it.id = it.id.toString()
return it
tags = _.map data.tags, (it) ->
it.id = it.name
return it
tagsWithAtLeastOneElement = _.filter tags, (tag) ->
return tag.count > 0
assignedTo = _.map data.assigned_to, (it) ->
if it.id
it.id = it.id.toString()
else
it.id = "null"
it.name = it.full_name || "Unassigned"
return it
owner = _.map data.owners, (it) ->
it.id = it.id.toString()
it.name = it.full_name
return it
@.selectedFilters = []
if loadFilters.status
selected = @.formatSelectedFilters("status", statuses, loadFilters.status)
@.selectedFilters = @.selectedFilters.concat(selected)
if loadFilters.tags
selected = @.formatSelectedFilters("tags", tags, loadFilters.tags)
@.selectedFilters = @.selectedFilters.concat(selected)
if loadFilters.assigned_to
selected = @.formatSelectedFilters("assigned_to", assignedTo, loadFilters.assigned_to)
@.selectedFilters = @.selectedFilters.concat(selected)
if loadFilters.owner
selected = @.formatSelectedFilters("owner", owner, loadFilters.owner)
@.selectedFilters = @.selectedFilters.concat(selected)
@.filterQ = loadFilters.q
@.filters = [
{
title: @translate.instant("COMMON.FILTERS.CATEGORIES.STATUS"),
dataType: "status",
content: statuses
},
{
title: @translate.instant("COMMON.FILTERS.CATEGORIES.TAGS"),
dataType: "tags",
content: tags,
hideEmpty: true,
totalTaggedElements: tagsWithAtLeastOneElement.length
},
{
title: @translate.instant("COMMON.FILTERS.CATEGORIES.ASSIGNED_TO"),
dataType: "assigned_to",
content: assignedTo
},
{
title: @translate.instant("COMMON.FILTERS.CATEGORIES.CREATED_BY"),
dataType: "owner",
content: owner
}
]
@.customFilters = []
_.forOwn customFiltersRaw, (value, key) =>
@.customFilters.push({id: key, name: key, filter: value})
_setMeta: -> _setMeta: ->
prettyDate = @translate.instant("BACKLOG.SPRINTS.DATE") prettyDate = @translate.instant("BACKLOG.SPRINTS.DATE")
@ -91,24 +250,33 @@ class TaskboardController extends mixOf(taiga.Controller, taiga.PageMixin)
@appMetaService.setAll(title, description) @appMetaService.setAll(title, description)
initializeEventHandlers: -> initializeEventHandlers: ->
# TODO: Reload entire taskboard after create/edit tasks seems @scope.$on "taskform:bulk:success", (event, tasks) =>
# a big overhead. It should be optimized in near future. @.refreshTagsColors().then () =>
@scope.$on "taskform:bulk:success", => @taskboardTasksService.add(tasks)
@.loadTaskboard()
@analytics.trackEvent("task", "create", "bulk create task on taskboard", 1) @analytics.trackEvent("task", "create", "bulk create task on taskboard", 1)
@scope.$on "taskform:new:success", => @scope.$on "taskform:new:success", (event, task) =>
@.loadTaskboard() @.refreshTagsColors().then () =>
@taskboardTasksService.add(task)
@analytics.trackEvent("task", "create", "create task on taskboard", 1) @analytics.trackEvent("task", "create", "create task on taskboard", 1)
@scope.$on("taskform:edit:success", => @.loadTaskboard()) @scope.$on "taskform:edit:success", (event, task) =>
@scope.$on("taskboard:task:move", @.taskMove) @.refreshTagsColors().then () =>
@taskboardTasksService.replaceModel(task)
@scope.$on "assigned-to:added", (ctx, userId, task) => @scope.$on("taskboard:task:move", @.taskMove)
task.assigned_to = userId @scope.$on("assigned-to:added", @.onAssignedToChanged)
promise = @repo.save(task)
promise.then null, -> onAssignedToChanged: (ctx, userid, taskModel) ->
console.log "FAIL" # TODO taskModel.assigned_to = userid
@taskboardTasksService.replaceModel(taskModel)
promise = @repo.save(taskModel)
promise.then null, ->
console.log "FAIL" # TODO
initializeSubscription: -> initializeSubscription: ->
routingKey = "changes.project.#{@scope.projectId}.tasks" routingKey = "changes.project.#{@scope.projectId}.tasks"
@ -124,12 +292,11 @@ class TaskboardController extends mixOf(taiga.Controller, taiga.PageMixin)
loadProject: -> loadProject: ->
return @rs.projects.get(@scope.projectId).then (project) => return @rs.projects.get(@scope.projectId).then (project) =>
if not project.is_backlog_activated if not project.is_backlog_activated
@location.path(@navUrls.resolve("permission-denied")) @errorHandlingService.permissionDenied()
@scope.project = project @scope.project = project
# Not used at this momment # Not used at this momment
@scope.pointsList = _.sortBy(project.points, "order") @scope.pointsList = _.sortBy(project.points, "order")
# @scope.roleList = _.sortBy(project.roles, "order")
@scope.pointsById = groupBy(project.points, (e) -> e.id) @scope.pointsById = groupBy(project.points, (e) -> e.id)
@scope.roleById = groupBy(project.roles, (e) -> e.id) @scope.roleById = groupBy(project.roles, (e) -> e.id)
@scope.taskStatusList = _.sortBy(project.task_statuses, "order") @scope.taskStatusList = _.sortBy(project.task_statuses, "order")
@ -163,40 +330,27 @@ class TaskboardController extends mixOf(taiga.Controller, taiga.PageMixin)
refreshTagsColors: -> refreshTagsColors: ->
return @rs.projects.tagsColors(@scope.projectId).then (tags_colors) => return @rs.projects.tagsColors(@scope.projectId).then (tags_colors) =>
@scope.project.tags_colors = tags_colors @scope.project.tags_colors = tags_colors._attrs
loadSprint: -> loadSprint: ->
return @rs.sprints.get(@scope.projectId, @scope.sprintId).then (sprint) => return @rs.sprints.get(@scope.projectId, @scope.sprintId).then (sprint) =>
@scope.sprint = sprint @scope.sprint = sprint
@scope.userstories = _.sortBy(sprint.user_stories, "sprint_order") @scope.userstories = _.sortBy(sprint.user_stories, "sprint_order")
@taskboardTasksService.setUserstories(@scope.userstories)
return sprint return sprint
loadTasks: -> loadTasks: ->
return @rs.tasks.list(@scope.projectId, @scope.sprintId).then (tasks) => params = {
@scope.tasks = _.sortBy(tasks, 'taskboard_order') include_attachments: true,
@scope.usTasks = {} }
# Iterate over all userstories and params = _.merge params, @location.search()
# null userstory for unassigned tasks
for us in _.union(@scope.userstories, [{id:null}])
@scope.usTasks[us.id] = {}
for status in @scope.taskStatusList
@scope.usTasks[us.id][status.id] = []
for task in @scope.tasks return @rs.tasks.list(@scope.projectId, @scope.sprintId, null, params).then (tasks) =>
if @scope.usTasks[task.user_story]? and @scope.usTasks[task.user_story][task.status]? @taskboardTasksService.init(@scope.project, @scope.usersById)
@scope.usTasks[task.user_story][task.status].push(task) @taskboardTasksService.set(tasks)
if tasks.length == 0
if @scope.userstories.length > 0
usId = @scope.userstories[0].id
else
usId = null
@scope.usTasks[usId][@scope.taskStatusList[0].id].push({isPlaceholder: true})
return tasks
loadTaskboard: -> loadTaskboard: ->
return @q.all([ return @q.all([
@ -218,60 +372,97 @@ class TaskboardController extends mixOf(taiga.Controller, taiga.PageMixin)
return data return data
return promise.then(=> @.loadProject()) return promise.then(=> @.loadProject())
.then(=> @.loadTaskboard()) .then =>
@.generateFilters()
refreshTasksOrder: (tasks) -> return @.loadTaskboard().then(=> @.setRolePoints())
items = @.resortTasks(tasks)
data = @.prepareBulkUpdateData(items)
return @rs.tasks.bulkUpdateTaskTaskboardOrder(@scope.project.id, data) showPlaceHolder: (statusId, usId) ->
if !@taskboardTasksService.tasksRaw.length
if @scope.taskStatusList[0].id == statusId &&
(!@scope.userstories.length || @scope.userstories[0].id == usId)
return true
resortTasks: (tasks) -> return false
items = []
for item, index in tasks editTask: (id) ->
item["taskboard_order"] = index task = @.taskboardTasksService.getTask(id)
if item.isModified()
items.push(item)
return items task = task.set('loading', true)
@taskboardTasksService.replace(task)
prepareBulkUpdateData: (uses) -> @rs.tasks.getByRef(task.getIn(['model', 'project']), task.getIn(['model', 'ref'])).then (editingTask) =>
return _.map(uses, (x) -> {"task_id": x.id, "order": x["taskboard_order"]}) @rs2.attachments.list("task", task.get('id'), task.getIn(['model', 'project'])).then (attachments) =>
@rootscope.$broadcast("taskform:edit", editingTask, attachments.toJS())
task = task.set('loading', false)
@taskboardTasksService.replace(task)
taskMove: (ctx, task, usId, statusId, order) -> taskMove: (ctx, task, oldStatusId, usId, statusId, order) ->
# Remove task from old position task = @taskboardTasksService.getTaskModel(task.get('id'))
r = @scope.usTasks[task.user_story][task.status].indexOf(task)
@scope.usTasks[task.user_story][task.status].splice(r, 1)
# Add task to new position moveUpdateData = @taskboardTasksService.move(task.id, usId, statusId, order)
tasks = @scope.usTasks[usId][statusId]
tasks.splice(order, 0, task)
task.user_story = usId params = {
task.status = statusId status__is_archived: false,
task.taskboard_order = order include_attachments: true,
}
promise = @repo.save(task) options = {
headers: {
"set-orders": JSON.stringify(moveUpdateData.set_orders)
}
}
@rootscope.$broadcast("sprint:task:moved", task) promise = @repo.save(task, true, params, options, true).then (result) =>
headers = result[1]
if headers && headers['taiga-info-order-updated']
order = JSON.parse(headers['taiga-info-order-updated'])
@taskboardTasksService.assignOrders(order)
promise.then =>
@.refreshTasksOrder(tasks)
@.loadSprintStats() @.loadSprintStats()
promise.then null, =>
console.log "FAIL TASK SAVE"
## Template actions ## Template actions
addNewTask: (type, us) -> addNewTask: (type, us) ->
switch type switch type
when "standard" then @rootscope.$broadcast("taskform:new", @scope.sprintId, us?.id) when "standard" then @rootscope.$broadcast("taskform:new", @scope.sprintId, us?.id)
when "bulk" then @rootscope.$broadcast("taskform:bulk", @scope.sprintId, us?.id) when "bulk" then @rootscope.$broadcast("taskform:bulk", @scope.sprintId, us?.id)
editTaskAssignedTo: (task) -> toggleFold: (id) ->
@taskboardTasksService.toggleFold(id)
changeTaskAssignedTo: (id) ->
task = @taskboardTasksService.getTaskModel(id)
@rootscope.$broadcast("assigned-to:add", task) @rootscope.$broadcast("assigned-to:add", task)
setRolePoints: () ->
computableRoles = _.filter(@scope.project.roles, "computable")
getRole = (roleId) =>
roleId = parseInt(roleId, 10)
return _.find computableRoles, (role) -> role.id == roleId
getPoint = (pointId) =>
poitnId = parseInt(pointId, 10)
return _.find @scope.project.points, (point) -> point.id == pointId
pointsByRole = _.reduce @scope.userstories, (result, us, key) =>
_.forOwn us.points, (pointId, roleId) ->
role = getRole(roleId)
point = getPoint(pointId)
if !result[role.id]
result[role.id] = role
result[role.id].points = 0
result[role.id].points += point.value
return result
, {}
@scope.pointsByRole = Object.keys(pointsByRole).map (key) -> return pointsByRole[key]
module.controller("TaskboardController", TaskboardController) module.controller("TaskboardController", TaskboardController)
@ -302,43 +493,6 @@ TaskboardDirective = ($rootscope) ->
module.directive("tgTaskboard", ["$rootScope", TaskboardDirective]) module.directive("tgTaskboard", ["$rootScope", TaskboardDirective])
#############################################################################
## Taskboard Task Directive
#############################################################################
TaskboardTaskDirective = ($rootscope, $loading, $rs, $rs2) ->
link = ($scope, $el, $attrs, $model) ->
$scope.$watch "task", (task) ->
if task.is_blocked and not $el.hasClass("blocked")
$el.addClass("blocked")
else if not task.is_blocked and $el.hasClass("blocked")
$el.removeClass("blocked")
$el.find(".edit-task").on "click", (event) ->
if $el.find('.edit-task').hasClass('noclick')
return
$scope.$apply ->
target = $(event.target)
currentLoading = $loading()
.target(target)
.timeout(200)
.start()
task = $scope.task
$rs.tasks.getByRef(task.project, task.ref).then (editingTask) =>
$rs2.attachments.list("task", editingTask.id, editingTask.project).then (attachments) =>
$rootscope.$broadcast("taskform:edit", editingTask, attachments.toJS())
currentLoading.finish()
return {link:link}
module.directive("tgTaskboardTask", ["$rootScope", "$tgLoading", "$tgResources", "tgResources", TaskboardTaskDirective])
############################################################################# #############################################################################
## Taskboard Squish Column Directive ## Taskboard Squish Column Directive
############################################################################# #############################################################################
@ -348,14 +502,18 @@ TaskboardSquishColumnDirective = (rs) ->
maxColumnWidth = 300 maxColumnWidth = 300
link = ($scope, $el, $attrs) -> link = ($scope, $el, $attrs) ->
$scope.$on "sprint:zoom0", () =>
recalculateTaskboardWidth()
$scope.$on "sprint:task:moved", () => $scope.$on "sprint:task:moved", () =>
recalculateTaskboardWidth() recalculateTaskboardWidth()
bindOnce $scope, "usTasks", (project) -> $scope.$watch "usTasks", () ->
$scope.statusesFolded = rs.tasks.getStatusColumnModes($scope.project.id) if $scope.project
$scope.usFolded = rs.tasks.getUsRowModes($scope.project.id, $scope.sprintId) $scope.statusesFolded = rs.tasks.getStatusColumnModes($scope.project.id)
$scope.usFolded = rs.tasks.getUsRowModes($scope.project.id, $scope.sprintId)
recalculateTaskboardWidth() recalculateTaskboardWidth()
$scope.foldStatus = (status) -> $scope.foldStatus = (status) ->
$scope.statusesFolded[status.id] = !!!$scope.statusesFolded[status.id] $scope.statusesFolded[status.id] = !!!$scope.statusesFolded[status.id]
@ -374,7 +532,10 @@ TaskboardSquishColumnDirective = (rs) ->
recalculateTaskboardWidth() recalculateTaskboardWidth()
getCeilWidth = (usId, statusId) => getCeilWidth = (usId, statusId) =>
tasks = $scope.usTasks[usId][statusId].length if usId
tasks = $scope.usTasks.getIn([usId.toString(), statusId.toString()]).size
else
tasks = $scope.usTasks.getIn(['null', statusId.toString()]).size
if $scope.statusesFolded[statusId] if $scope.statusesFolded[statusId]
if tasks and $scope.usFolded[usId] if tasks and $scope.usFolded[usId]
@ -393,7 +554,10 @@ TaskboardSquishColumnDirective = (rs) ->
if width if width
column.css('max-width', width) column.css('max-width', width)
else else
column.css("max-width", maxColumnWidth) if $scope.ctrl.zoomLevel == '0'
column.css("max-width", 148)
else
column.css("max-width", maxColumnWidth)
refreshTaskboardTableWidth = () => refreshTaskboardTableWidth = () =>
columnWidths = [] columnWidths = []
@ -429,65 +593,3 @@ TaskboardSquishColumnDirective = (rs) ->
return {link: link} return {link: link}
module.directive("tgTaskboardSquishColumn", ["$tgResources", TaskboardSquishColumnDirective]) module.directive("tgTaskboardSquishColumn", ["$tgResources", TaskboardSquishColumnDirective])
#############################################################################
## Taskboard User Directive
#############################################################################
TaskboardUserDirective = ($log, $translate) ->
clickable = false
link = ($scope, $el, $attrs) ->
username_label = $el.parent().find("a.task-assigned")
username_label.addClass("not-clickable")
$scope.$watch 'task.assigned_to', (assigned_to) ->
user = $scope.usersById[assigned_to]
if user is undefined
_.assign($scope, {
name: $translate.instant("COMMON.ASSIGNED_TO.NOT_ASSIGNED"),
imgurl: "/#{window._version}/images/unnamed.png",
clickable: clickable
})
else
_.assign($scope, {
name: user.full_name_display,
imgurl: user.photo,
clickable: clickable
})
username_label.text($scope.name)
bindOnce $scope, "project", (project) ->
if project.my_permissions.indexOf("modify_task") > -1
clickable = true
$el.find(".avatar-assigned-to").on "click", (event) =>
if $el.find('a').hasClass('noclick')
return
$ctrl = $el.controller()
$ctrl.editTaskAssignedTo($scope.task)
username_label.removeClass("not-clickable")
username_label.on "click", (event) ->
if $el.find('a').hasClass('noclick')
return
$ctrl = $el.controller()
$ctrl.editTaskAssignedTo($scope.task)
return {
link: link,
templateUrl: "taskboard/taskboard-user.html",
scope: {
"usersById": "=users",
"project": "=",
"task": "=",
}
}
module.directive("tgTaskboardUserAvatar", ["$log", "$translate", TaskboardUserDirective])

View File

@ -37,11 +37,14 @@ module = angular.module("taigaBacklog")
## Sortable Directive ## Sortable Directive
############################################################################# #############################################################################
TaskboardSortableDirective = ($repo, $rs, $rootscope) -> TaskboardSortableDirective = ($repo, $rs, $rootscope, $translate) ->
link = ($scope, $el, $attrs) -> link = ($scope, $el, $attrs) ->
bindOnce $scope, "tasks", (xx) -> unwatch = $scope.$watch "usTasks", (usTasks) ->
# If the user has not enough permissions we don't enable the sortable return if !usTasks || !usTasks.size
if not ($scope.project.my_permissions.indexOf("modify_us") > -1)
unwatch()
if not ($scope.project.my_permissions.indexOf("modify_task") > -1)
return return
oldParentScope = null oldParentScope = null
@ -49,6 +52,10 @@ TaskboardSortableDirective = ($repo, $rs, $rootscope) ->
itemEl = null itemEl = null
tdom = $el tdom = $el
filterError = ->
text = $translate.instant("BACKLOG.SORTABLE_FILTER_ERROR")
$tgConfirm.notify("error", text)
deleteElement = (itemEl) -> deleteElement = (itemEl) ->
# Completelly remove item and its scope from dom # Completelly remove item and its scope from dom
itemEl.scope().$destroy() itemEl.scope().$destroy()
@ -62,12 +69,23 @@ TaskboardSortableDirective = ($repo, $rs, $rootscope) ->
copySortSource: false, copySortSource: false,
copy: false, copy: false,
mirrorContainer: $el[0], mirrorContainer: $el[0],
moves: (item) -> return $(item).hasClass('taskboard-task') accepts: (el, target) -> return !$(target).hasClass('taskboard-userstory-box')
moves: (item) ->
return $(item).is('tg-card')
}) })
drake.on 'drag', (item) -> drake.on 'drag', (item) ->
oldParentScope = $(item).parent().scope() oldParentScope = $(item).parent().scope()
if $el.hasClass("active-filters")
filterError()
setTimeout (() ->
drake.cancel(true)
), 0
return false
drake.on 'dragend', (item) -> drake.on 'dragend', (item) ->
parentEl = $(item).parent() parentEl = $(item).parent()
itemEl = $(item) itemEl = $(item)
@ -84,14 +102,15 @@ TaskboardSortableDirective = ($repo, $rs, $rootscope) ->
deleteElement(itemEl) deleteElement(itemEl)
$scope.$apply -> $scope.$apply ->
$rootscope.$broadcast("taskboard:task:move", itemTask, newUsId, newStatusId, itemIndex) $rootscope.$broadcast("taskboard:task:move", itemTask, itemTask.getIn(['model', 'status']), newUsId, newStatusId, itemIndex)
scroll = autoScroll([$('.taskboard-table-body')[0]], { scroll = autoScroll([$('.taskboard-table-body')[0]], {
margin: 20, margin: 100,
pixels: 30, pixels: 30,
scrollWhenOutside: true, scrollWhenOutside: true,
autoScroll: () -> autoScroll: () ->
return this.down && drake.dragging; return this.down && drake.dragging
}) })
$scope.$on "$destroy", -> $scope.$on "$destroy", ->
@ -105,5 +124,6 @@ module.directive("tgTaskboardSortable", [
"$tgRepo", "$tgRepo",
"$tgResources", "$tgResources",
"$rootScope", "$rootScope",
"$translate",
TaskboardSortableDirective TaskboardSortableDirective
]) ])

View File

@ -0,0 +1,172 @@
###
# Copyright (C) 2014-2016 Taiga Agile LLC <taiga@taiga.io>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# File: home.service.coffee
###
groupBy = @.taiga.groupBy
class TaskboardTasksService extends taiga.Service
@.$inject = []
constructor: () ->
@.reset()
reset: () ->
@.tasksRaw = []
@.foldStatusChanged = {}
@.usTasks = Immutable.Map()
init: (project, usersById) ->
@.project = project
@.usersById = usersById
resetFolds: () ->
@.foldStatusChanged = {}
@.refresh()
toggleFold: (taskId) ->
@.foldStatusChanged[taskId] = !@.foldStatusChanged[taskId]
@.refresh()
add: (task) ->
@.tasksRaw = @.tasksRaw.concat(task)
@.refresh()
set: (tasks) ->
@.tasksRaw = tasks
@.refreshRawOrder()
@.refresh()
setUserstories: (userstories) ->
@.userstories = userstories
refreshRawOrder: () ->
@.order = {}
@.order[task.id] = task.taskboard_order for task in @.tasksRaw
assignOrders: (order) ->
order = _.invert(order)
@.order = _.assign(@.order, order)
@.refresh()
getTask: (id) ->
findedTask = null
@.usTasks.forEach (us) ->
us.forEach (status) ->
findedTask = status.find (task) -> return task.get('id') == id
return false if findedTask
return false if findedTask
return findedTask
replace: (task) ->
@.usTasks = @.usTasks.map (us) ->
return us.map (status) ->
findedIndex = status.findIndex (usItem) ->
return usItem.get('id') == us.get('id')
if findedIndex != -1
status = status.set(findedIndex, task)
return status
getTaskModel: (id) ->
return _.find @.tasksRaw, (task) -> return task.id == id
replaceModel: (task) ->
@.tasksRaw = _.map @.tasksRaw, (it) ->
if task.id == it.id
return task
else
return it
@.refresh()
move: (id, usId, statusId, index) ->
task = @.getTaskModel(id)
taskByUsStatus = _.filter @.tasksRaw, (task) =>
return task.status == statusId && task.user_story == usId
taskByUsStatus = _.sortBy taskByUsStatus, (it) => @.order[it.id]
taksWithoutMoved = _.filter taskByUsStatus, (it) => it.id != id
beforeDestination = _.slice(taksWithoutMoved, 0, index)
afterDestination = _.slice(taksWithoutMoved, index)
setOrders = {}
previous = beforeDestination[beforeDestination.length - 1]
previousWithTheSameOrder = _.filter beforeDestination, (it) =>
@.order[it.id] == @.order[previous.id]
if previousWithTheSameOrder.length > 1
for it in previousWithTheSameOrder
setOrders[it.id] = @.order[it.id]
if !previous
@.order[task.id] = 0
else if previous
@.order[task.id] = @.order[previous.id] + 1
for it, key in afterDestination
@.order[it.id] = @.order[task.id] + key + 1
task.status = statusId
task.user_story = usId
task.taskboard_order = @.order[task.id]
@.refresh()
return {"task_id": task.id, "order": @.order[task.id], "set_orders": setOrders}
refresh: ->
@.tasksRaw = _.sortBy @.tasksRaw, (it) => @.order[it.id]
tasks = @.tasksRaw
taskStatusList = _.sortBy(@.project.task_statuses, "order")
usTasks = {}
# Iterate over all userstories and
# null userstory for unassigned tasks
for us in _.union(@.userstories, [{id:null}])
usTasks[us.id] = {}
for status in taskStatusList
usTasks[us.id][status.id] = []
for taskModel in tasks
if usTasks[taskModel.user_story]? and usTasks[taskModel.user_story][taskModel.status]?
task = {}
task.foldStatusChanged = @.foldStatusChanged[taskModel.id]
task.model = taskModel.getAttrs()
task.images = _.filter taskModel.attachments, (it) -> return !!it.thumbnail_card_url
task.id = taskModel.id
task.assigned_to = @.usersById[taskModel.assigned_to]
task.colorized_tags = _.map task.model.tags, (tag) =>
return {name: tag[0], color: tag[1]}
usTasks[taskModel.user_story][taskModel.status].push(task)
@.usTasks = Immutable.fromJS(usTasks)
angular.module("taigaKanban").service("tgTaskboardTasks", TaskboardTasksService)

View File

@ -50,11 +50,12 @@ class TaskDetailController extends mixOf(taiga.Controller, taiga.PageMixin)
"$tgNavUrls", "$tgNavUrls",
"$tgAnalytics", "$tgAnalytics",
"$translate", "$translate",
"$tgQueueModelTransformation" "$tgQueueModelTransformation",
"tgErrorHandlingService"
] ]
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location,
@log, @appMetaService, @navUrls, @analytics, @translate, @modelTransform) -> @log, @appMetaService, @navUrls, @analytics, @translate, @modelTransform, @errorHandlingService) ->
bindMethods(@) bindMethods(@)
@scope.taskRef = @params.taskref @scope.taskRef = @params.taskref

View File

@ -45,11 +45,12 @@ class TeamController extends mixOf(taiga.Controller, taiga.PageMixin)
"tgAppMetaService", "tgAppMetaService",
"$tgAuth", "$tgAuth",
"$translate", "$translate",
"tgProjectService" "tgProjectService",
"tgErrorHandlingService"
] ]
constructor: (@scope, @rootscope, @repo, @rs, @params, @q, @location, @navUrls, @appMetaService, @auth, constructor: (@scope, @rootscope, @repo, @rs, @params, @q, @location, @navUrls, @appMetaService, @auth,
@translate, @projectService) -> @translate, @projectService, @errorHandlingService) ->
@scope.sectionName = "TEAM.SECTION_NAME" @scope.sectionName = "TEAM.SECTION_NAME"
promise = @.loadInitialData() promise = @.loadInitialData()
@ -80,6 +81,8 @@ class TeamController extends mixOf(taiga.Controller, taiga.PageMixin)
for member in @scope.activeUsers for member in @scope.activeUsers
@scope.totals[member.id] = 0 @scope.totals[member.id] = 0
console.log @scope.activeUsers
# Get current user # Get current user
@scope.currentUser = _.find(@scope.activeUsers, {id: user?.id}) @scope.currentUser = _.find(@scope.activeUsers, {id: user?.id})

View File

@ -45,19 +45,19 @@ class UserSettingsController extends mixOf(taiga.Controller, taiga.PageMixin)
"$tgLocation", "$tgLocation",
"$tgNavUrls", "$tgNavUrls",
"$tgAuth", "$tgAuth",
"$translate" "$translate",
"tgErrorHandlingService"
] ]
constructor: (@scope, @rootscope, @config, @repo, @confirm, @rs, @params, @q, @location, @navUrls, constructor: (@scope, @rootscope, @config, @repo, @confirm, @rs, @params, @q, @location, @navUrls,
@auth, @translate) -> @auth, @translate, @errorHandlingService) ->
@scope.sectionName = "USER_SETTINGS.MENU.SECTION_TITLE" @scope.sectionName = "USER_SETTINGS.MENU.SECTION_TITLE"
@scope.project = {} @scope.project = {}
@scope.user = @auth.getUser() @scope.user = @auth.getUser()
if !@scope.user if !@scope.user
@location.path(@navUrls.resolve("permission-denied")) @errorHandlingService.permissionDenied()
@location.replace()
@scope.lang = @getLan() @scope.lang = @getLan()
@scope.theme = @getTheme() @scope.theme = @getTheme()

View File

@ -44,10 +44,11 @@ class UserNotificationsController extends mixOf(taiga.Controller, taiga.PageMixi
"$q", "$q",
"$tgLocation", "$tgLocation",
"$tgNavUrls", "$tgNavUrls",
"$tgAuth" "$tgAuth",
"tgErrorHandlingService"
] ]
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, @navUrls, @auth) -> constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, @navUrls, @auth, @errorHandlingService) ->
@scope.sectionName = "USER_SETTINGS.NOTIFICATIONS.SECTION_NAME" @scope.sectionName = "USER_SETTINGS.NOTIFICATIONS.SECTION_NAME"
@scope.user = @auth.getUser() @scope.user = @auth.getUser()
promise = @.loadInitialData() promise = @.loadInitialData()

View File

@ -50,12 +50,13 @@ class UserStoryDetailController extends mixOf(taiga.Controller, taiga.PageMixin)
"$tgNavUrls", "$tgNavUrls",
"$tgAnalytics", "$tgAnalytics",
"$translate", "$translate",
"$tgConfig", "$tgQueueModelTransformation",
"$tgQueueModelTransformation" "tgErrorHandlingService",
"$tgConfig"
] ]
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, @log, @appMetaService, constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location,
@navUrls, @analytics, @translate, @configService, @modelTransform) -> @log, @appMetaService, @navUrls, @analytics, @translate, @modelTransform, @errorHandlingService, @configService) ->
bindMethods(@) bindMethods(@)
@scope.usRef = @params.usref @scope.usRef = @params.usref
@ -165,20 +166,6 @@ class UserStoryDetailController extends mixOf(taiga.Controller, taiga.PageMixin)
@modelTransform.setObject(@scope, 'us') @modelTransform.setObject(@scope, 'us')
if @scope.us.neighbors.previous?.ref?
ctx = {
project: @scope.project.slug
ref: @scope.us.neighbors.previous.ref
}
@scope.previousUrl = @navUrls.resolve("project-userstories-detail", ctx)
if @scope.us.neighbors.next?.ref?
ctx = {
project: @scope.project.slug
ref: @scope.us.neighbors.next.ref
}
@scope.nextUrl = @navUrls.resolve("project-userstories-detail", ctx)
return us return us
loadSprint: -> loadSprint: ->
@ -330,7 +317,7 @@ UsStatusButtonDirective = ($rootScope, $repo, $confirm, $loading, $modelTransfor
$el.html(html) $el.html(html)
$compile($el.contents())($scope); $compile($el.contents())($scope)
save = (status) => save = (status) =>
$el.find(".pop-status").popover().close() $el.find(".pop-status").popover().close()

View File

@ -51,11 +51,13 @@ class WikiDetailController extends mixOf(taiga.Controller, taiga.PageMixin)
"tgAppMetaService", "tgAppMetaService",
"$tgNavUrls", "$tgNavUrls",
"$tgAnalytics", "$tgAnalytics",
"$translate" "$translate",
"tgErrorHandlingService"
] ]
constructor: (@scope, @rootscope, @repo, @model, @confirm, @rs, @params, @q, @location, constructor: (@scope, @rootscope, @repo, @model, @confirm, @rs, @params, @q, @location,
@filter, @log, @appMetaService, @navUrls, @analytics, @translate) -> @filter, @log, @appMetaService, @navUrls, @analytics, @translate, @errorHandlingService) ->
@scope.$on("wiki:links:move", @.moveLink)
@scope.projectSlug = @params.pslug @scope.projectSlug = @params.pslug
@scope.wikiSlug = @params.slug @scope.wikiSlug = @params.slug
@scope.wikiTitle = @scope.wikiSlug @scope.wikiTitle = @scope.wikiSlug
@ -86,7 +88,7 @@ class WikiDetailController extends mixOf(taiga.Controller, taiga.PageMixin)
loadProject: -> loadProject: ->
return @rs.projects.getBySlug(@params.pslug).then (project) => return @rs.projects.getBySlug(@params.pslug).then (project) =>
if not project.is_wiki_activated if not project.is_wiki_activated
@location.path(@navUrls.resolve("permission-denied")) @errorHandlingService.permissionDenied()
@scope.projectId = project.id @scope.projectId = project.id
@scope.project = project @scope.project = project
@ -155,6 +157,16 @@ class WikiDetailController extends mixOf(taiga.Controller, taiga.PageMixin)
@repo.remove(@scope.wiki).then onSuccess, onError @repo.remove(@scope.wiki).then onSuccess, onError
moveLink: (ctx, item, itemIndex) =>
values = @scope.wikiLinks
r = values.indexOf(item)
values.splice(r, 1)
values.splice(itemIndex, 0, item)
_.each values, (value, index) ->
value.order = index
@repo.saveAll(values)
module.controller("WikiDetailController", WikiDetailController) module.controller("WikiDetailController", WikiDetailController)
@ -162,7 +174,7 @@ module.controller("WikiDetailController", WikiDetailController)
## Wiki Summary Directive ## Wiki Summary Directive
############################################################################# #############################################################################
WikiSummaryDirective = ($log, $template, $compile, $translate) -> WikiSummaryDirective = ($log, $template, $compile, $translate, avatarService) ->
template = $template.get("wiki/wiki-summary.html", true) template = $template.get("wiki/wiki-summary.html", true)
link = ($scope, $el, $attrs, $model) -> link = ($scope, $el, $attrs, $model) ->
@ -172,10 +184,12 @@ WikiSummaryDirective = ($log, $template, $compile, $translate) ->
else else
user = $scope.usersById[wiki.last_modifier] user = $scope.usersById[wiki.last_modifier]
avatar = avatarService.getAvatar(user)
if user is undefined if user is undefined
user = {name: "unknown", imgUrl: "/" + window._version + "/images/user-noimage.png"} user = {name: "unknown", avatar: avatar}
else else
user = {name: user.full_name_display, imgUrl: user.photo} user = {name: user.full_name_display, avatar: avatar}
ctx = { ctx = {
totalEditions: wiki.editions totalEditions: wiki.editions
@ -199,14 +213,15 @@ WikiSummaryDirective = ($log, $template, $compile, $translate) ->
require: "ngModel" require: "ngModel"
} }
module.directive("tgWikiSummary", ["$log", "$tgTemplate", "$compile", "$translate", WikiSummaryDirective]) module.directive("tgWikiSummary", ["$log", "$tgTemplate", "$compile", "$translate", "tgAvatarService", WikiSummaryDirective])
############################################################################# #############################################################################
## Editable Wiki Content Directive ## Editable Wiki Content Directive
############################################################################# #############################################################################
EditableWikiContentDirective = ($window, $document, $repo, $confirm, $loading, $analytics, $qqueue, $translate) -> EditableWikiContentDirective = ($window, $document, $repo, $confirm, $loading, $analytics, $qqueue, $translate,
$wikiHistoryService) ->
link = ($scope, $el, $attrs, $model) -> link = ($scope, $el, $attrs, $model) ->
isEditable = -> isEditable = ->
return $scope.project.my_permissions.indexOf("modify_wiki_page") != -1 return $scope.project.my_permissions.indexOf("modify_wiki_page") != -1
@ -228,7 +243,6 @@ EditableWikiContentDirective = ($window, $document, $repo, $confirm, $loading, $
return if not $model.$modelValue.id return if not $model.$modelValue.id
$model.$modelValue.revert() $model.$modelValue.revert()
switchToReadMode() switchToReadMode()
getSelectedText = -> getSelectedText = ->
@ -245,6 +259,7 @@ EditableWikiContentDirective = ($window, $document, $repo, $confirm, $loading, $
$model.$setViewValue wikiPage.clone() $model.$setViewValue wikiPage.clone()
$wikiHistoryService.loadHistoryEntries()
$confirm.notify("success") $confirm.notify("success")
switchToReadMode() switchToReadMode()
@ -252,8 +267,7 @@ EditableWikiContentDirective = ($window, $document, $repo, $confirm, $loading, $
$confirm.notify("error") $confirm.notify("error")
currentLoading = $loading() currentLoading = $loading()
.removeClasses("icon-floppy") .target($el.find('.save'))
.target($el.find('.icon-floppy'))
.start() .start()
if wiki.id? if wiki.id?
@ -322,4 +336,5 @@ EditableWikiContentDirective = ($window, $document, $repo, $confirm, $loading, $
} }
module.directive("tgEditableWikiContent", ["$window", "$document", "$tgRepo", "$tgConfirm", "$tgLoading", module.directive("tgEditableWikiContent", ["$window", "$document", "$tgRepo", "$tgConfirm", "$tgLoading",
"$tgAnalytics", "$tgQqueue", "$translate", EditableWikiContentDirective]) "$tgAnalytics", "$tgQqueue", "$translate", "tgWikiHistoryService",
EditableWikiContentDirective])

View File

@ -38,12 +38,16 @@ module = angular.module("taigaWiki")
WikiNavDirective = ($tgrepo, $log, $location, $confirm, $analytics, $loading, $template, WikiNavDirective = ($tgrepo, $log, $location, $confirm, $analytics, $loading, $template,
$compile, $translate) -> $compile, $translate) ->
template = $template.get("wiki/wiki-nav.html", true) template = $template.get("wiki/wiki-nav.html", true)
link = ($scope, $el, $attrs) ->
linkWikiLinks = ($scope, $el, $attrs) ->
$ctrl = $el.controller() $ctrl = $el.controller()
if not $attrs.ngModel? if not $attrs.ngModel?
return $log.error "WikiNavDirective: no ng-model attr is defined" return $log.error "WikiNavDirective: no ng-model attr is defined"
addWikiLinkPermission = $scope.project.my_permissions.indexOf("add_wiki_link") > -1
drake = null
render = (wikiLinks) -> render = (wikiLinks) ->
addWikiLinkPermission = $scope.project.my_permissions.indexOf("add_wiki_link") > -1 addWikiLinkPermission = $scope.project.my_permissions.indexOf("add_wiki_link") > -1
deleteWikiLinkPermission = $scope.project.my_permissions.indexOf("delete_wiki_link") > -1 deleteWikiLinkPermission = $scope.project.my_permissions.indexOf("delete_wiki_link") > -1
@ -58,8 +62,37 @@ WikiNavDirective = ($tgrepo, $log, $location, $confirm, $analytics, $loading, $t
html = $compile(html)($scope) html = $compile(html)($scope)
$el.off() $el.off()
if addWikiLinkPermission and drake
drake.destroy()
$el.html(html) $el.html(html)
if addWikiLinkPermission
itemEl = null
tdom = $el.find(".sortable")
drake = dragula([tdom[0]], {
direction: 'vertical',
copySortSource: false,
copy: false,
mirrorContainer: tdom[0],
moves: (item) -> return $(item).is('li')
})
drake.on 'dragend', (item) ->
itemEl = $(item)
item = itemEl.scope().link
itemIndex = itemEl.index()
$scope.$emit("wiki:links:move", item, itemIndex)
scroll = autoScroll(window, {
margin: 20,
pixels: 30,
scrollWhenOutside: true,
autoScroll: () ->
return this.down && drake.dragging
})
$el.on "click", ".add-button", (event) -> $el.on "click", ".add-button", (event) ->
event.preventDefault() event.preventDefault()
$el.find(".new").removeClass("hidden") $el.find(".new").removeClass("hidden")
@ -130,9 +163,14 @@ WikiNavDirective = ($tgrepo, $log, $location, $confirm, $analytics, $loading, $t
$el.find(".new input").val('') $el.find(".new input").val('')
$el.find(".add-button").show() $el.find(".add-button").show()
bindOnce($scope, $attrs.ngModel, render) bindOnce($scope, $attrs.ngModel, render)
link = ($scope, $el, $attrs) ->
linkWikiLinks($scope, $el, $attrs)
$scope.$on "$destroy", ->
$el.off()
return {link:link} return {link:link}
module.directive("tgWikiNav", ["$tgRepo", "$log", "$tgLocation", "$tgConfirm", "$tgAnalytics", module.directive("tgWikiNav", ["$tgRepo", "$log", "$tgLocation", "$tgConfirm", "$tgAnalytics",

View File

@ -0,0 +1,100 @@
###
# Copyright (C) 2014-2016 Andrey Antukh <niwi@niwi.nz>
# Copyright (C) 2014-2016 Jesús Espino Garcia <jespinog@gmail.com>
# Copyright (C) 2014-2016 David Barragán Merino <bameda@dbarragan.com>
# Copyright (C) 2014-2016 Alejandro Alonso <alejandro.alonso@kaleidos.net>
# Copyright (C) 2014-2016 Juan Francisco Alcántara <juanfran.alcantara@kaleidos.net>
# Copyright (C) 2014-2016 Xavi Julian <xavier.julian@kaleidos.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# File: modules/wiki/pages-list.coffee
###
taiga = @.taiga
mixOf = @.taiga.mixOf
module = angular.module("taigaWiki")
#############################################################################
## Wiki Pages List Controller
#############################################################################
class WikiPagesListController extends mixOf(taiga.Controller, taiga.PageMixin)
@.$inject = [
"$scope",
"$rootScope",
"$tgRepo",
"$tgModel",
"$tgConfirm",
"$tgResources",
"$routeParams",
"$q",
"$tgNavUrls",
"tgErrorHandlingService"
]
constructor: (@scope, @rootscope, @repo, @model, @confirm, @rs, @params, @q,
@navUrls, @errorHandlingService) ->
@scope.projectSlug = @params.pslug
@scope.wikiSlug = @params.slug
@scope.wikiTitle = @scope.wikiSlug
@scope.sectionName = "Wiki"
@scope.linksVisible = false
promise = @.loadInitialData()
# On Error
promise.then null, @.onInitialDataError.bind(@)
loadProject: ->
return @rs.projects.getBySlug(@params.pslug).then (project) =>
if not project.is_wiki_activated
@errorHandlingService.permissionDenied()
@scope.projectId = project.id
@scope.project = project
@scope.$emit('project:loaded', project)
return project
loadWikiPages: ->
promise = @rs.wiki.list(@scope.projectId).then (wikipages) =>
@scope.wikipages = wikipages
loadWikiLinks: ->
return @rs.wiki.listLinks(@scope.projectId).then (wikiLinks) =>
@scope.wikiLinks = wikiLinks
for link in @scope.wikiLinks
link.url = @navUrls.resolve("project-wiki-page", {
project: @scope.projectSlug
slug: link.href
})
selectedWikiLink = _.find(wikiLinks, {href: @scope.wikiSlug})
@scope.wikiTitle = selectedWikiLink.title if selectedWikiLink?
loadInitialData: ->
promise = @.loadProject()
return promise.then (project) =>
@.fillUsersAndRoles(project.members, project.roles)
@q.all([@.loadWikiLinks(), @.loadWikiPages()]).then @.checkLinksPerms.bind(this)
checkLinksPerms: ->
if @scope.project.my_permissions.indexOf("add_wiki_link") != -1 ||
(@scope.project.my_permissions.indexOf("view_wiki_links") != -1 && @scope.wikiLinks.length)
@scope.linksVisible = true
module.controller("WikiPagesListController", WikiPagesListController)

View File

@ -28,21 +28,24 @@ addClass = (el, className) ->
else else
el.className += ' ' + className el.className += ' ' + className
nl2br = (str) => nl2br = (str) =>
breakTag = '<br />' breakTag = '<br />'
return (str + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + breakTag + '$2') return (str + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + breakTag + '$2')
bindMethods = (object) => bindMethods = (object) =>
dependencies = _.keys(object) dependencies = _.keys(object)
methods = [] methods = []
_.forIn object, (value, key) => _.forIn object, (value, key) =>
if key not in dependencies if key not in dependencies && _.isFunction(value)
methods.push(key) methods.push(key)
_.bindAll(object, methods) _.bindAll(object, methods)
bindOnce = (scope, attr, continuation) => bindOnce = (scope, attr, continuation) =>
val = scope.$eval(attr) val = scope.$eval(attr)
if val != undefined if val != undefined
@ -75,6 +78,7 @@ slugify = (data) ->
.replace(/[^\w\-]+/g, '') .replace(/[^\w\-]+/g, '')
.replace(/\-\-+/g, '-') .replace(/\-\-+/g, '-')
unslugify = (data) -> unslugify = (data) ->
if data if data
return _.capitalize(data.replace(/-/g, ' ')) return _.capitalize(data.replace(/-/g, ' '))
@ -165,6 +169,7 @@ sizeFormat = (input, precision=1) ->
size = (input / Math.pow(1024, number)).toFixed(precision) size = (input / Math.pow(1024, number)).toFixed(precision)
return "#{size} #{units[number]}" return "#{size} #{units[number]}"
stripTags = (str, exception) -> stripTags = (str, exception) ->
if exception if exception
pattern = new RegExp('<(?!' + exception + '\s*\/?)[^>]+>', 'gi') pattern = new RegExp('<(?!' + exception + '\s*\/?)[^>]+>', 'gi')
@ -172,6 +177,7 @@ stripTags = (str, exception) ->
else else
return String(str).replace(/<\/?[^>]+>/g, '') return String(str).replace(/<\/?[^>]+>/g, '')
replaceTags = (str, tags, replace) -> replaceTags = (str, tags, replace) ->
# open tag # open tag
pattern = new RegExp('<(' + tags + ')>', 'gi') pattern = new RegExp('<(' + tags + ')>', 'gi')
@ -183,6 +189,7 @@ replaceTags = (str, tags, replace) ->
return str return str
defineImmutableProperty = (obj, name, fn) => defineImmutableProperty = (obj, name, fn) =>
Object.defineProperty obj, name, { Object.defineProperty obj, name, {
get: () => get: () =>
@ -197,6 +204,7 @@ defineImmutableProperty = (obj, name, fn) =>
return fn_result return fn_result
} }
_.mixin _.mixin
removeKeys: (obj, keys) -> removeKeys: (obj, keys) ->
_.chain([keys]).flatten().reduce( _.chain([keys]).flatten().reduce(
@ -211,10 +219,14 @@ _.mixin
, [ [] ]) , [ [] ])
isImage = (name) -> isImage = (name) ->
return name.match(/\.(jpe?g|png|gif|gifv|webm)/i) != null return name.match(/\.(jpe?g|png|gif|gifv|webm)/i) != null
isPdf = (name) ->
return name.match(/\.(pdf)/i) != null
patch = (oldImmutable, newImmutable) -> patch = (oldImmutable, newImmutable) ->
pathObj = {} pathObj = {}
@ -227,6 +239,18 @@ patch = (oldImmutable, newImmutable) ->
return pathObj return pathObj
DEFAULT_COLOR_LIST = [
'#fce94f', '#edd400', '#c4a000', '#8ae234', '#73d216', '#4e9a06', '#d3d7cf',
'#fcaf3e', '#f57900', '#ce5c00', '#729fcf', '#3465a4', '#204a87', '#888a85',
'#ad7fa8', '#75507b', '#5c3566', '#ef2929', '#cc0000', '#a40000', '#222222'
]
getRandomDefaultColor = () ->
return _.sample(DEFAULT_COLOR_LIST)
getDefaulColorList = () ->
return _.clone(DEFAULT_COLOR_LIST)
taiga = @.taiga taiga = @.taiga
taiga.addClass = addClass taiga.addClass = addClass
taiga.nl2br = nl2br taiga.nl2br = nl2br
@ -252,4 +276,7 @@ taiga.stripTags = stripTags
taiga.replaceTags = replaceTags taiga.replaceTags = replaceTags
taiga.defineImmutableProperty = defineImmutableProperty taiga.defineImmutableProperty = defineImmutableProperty
taiga.isImage = isImage taiga.isImage = isImage
taiga.isPdf = isPdf
taiga.patch = patch taiga.patch = patch
taiga.getRandomDefaultColor = getRandomDefaultColor
taiga.getDefaulColorList = getDefaulColorList

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 730 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 746 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 770 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 722 B

BIN
app/images/epics-empty.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1005 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -20,9 +20,14 @@ html(lang="en")
window.prerenderReady = false; window.prerenderReady = false;
body(tg-main) body(tg-main)
div(tg-navigation-bar) div(tg-navigation-bar, ng-if="!errorHandling.showingError")
div(ng-if="!errorHandling.showingError")
div.master(ng-view)
div.master(ng-view) div(ng-if="errorHandling.notfound", ng-include="'error/not-found.html'")
div(ng-if="errorHandling.error", ng-include="'error/error.html'")
div(ng-if="errorHandling.permissionDenied", ng-include="'error/permission-denied.html'")
div(ng-if="errorHandling.blocked", ng-include="'projects/project/blocked-project.html'")
div.lightbox.lightbox-generic-ask div.lightbox.lightbox-generic-ask
include partials/includes/modules/lightbox-generic-ask include partials/includes/modules/lightbox-generic-ask

View File

@ -464,13 +464,70 @@
}; };
var createPointCB = function createPointCB(object){
// A persistent object (as opposed to returned object) is used to save memory
// This is good to prevent layout thrashing, or for games, and such
// NOTE
// This uses IE fixes which should be OK to remove some day. :)
// Some speed will be gained by removal of these.
// pointCB should be saved in a variable on return
// This allows the usage of element.removeEventListener
return function pointCB(event){
event = event || window.event; // IE-ism
object.target = event.target || event.srcElement || event.originalTarget;
object.element = this;
object.type = event.type;
// Support touch
// http://www.creativebloq.com/javascript/make-your-site-work-touch-devices-51411644
if(event.targetTouches){
object.x = event.targetTouches[0].clientX;
object.y = event.targetTouches[0].clientY;
object.pageX = event.pageX;
object.pageY = event.pageY;
}else{
// If pageX/Y aren't available and clientX/Y are,
// calculate pageX/Y - logic taken from jQuery.
// (This is to support old IE)
// NOTE Hopefully this can be removed soon.
if (event.pageX === null && event.clientX !== null) {
var eventDoc = (event.target && event.target.ownerDocument) || document;
var doc = eventDoc.documentElement;
var body = eventDoc.body;
object.pageX = event.clientX +
(doc && doc.scrollLeft || body && body.scrollLeft || 0) -
(doc && doc.clientLeft || body && body.clientLeft || 0);
object.pageY = event.clientY +
(doc && doc.scrollTop || body && body.scrollTop || 0) -
(doc && doc.clientTop || body && body.clientTop || 0 );
}else{
object.pageX = event.pageX;
object.pageY = event.pageY;
}
// pageX, and pageY change with page scroll
// so we're not going to use those for x, and y.
// NOTE Most browsers also alias clientX/Y with x/y
// so that's something to consider down the road.
object.x = event.clientX;
object.y = event.clientY;
}
};
//NOTE Remember accessibility, Aria roles, and labels.
};
// Autscroller // Autscroller
function AutoScrollerFactory(element, options){
return new AutoScroller(element, options);
}
function AutoScroller(elements, options){ function AutoScroller(elements, options){
var self = this, pixels = 2; var self = this, pixels = 2;
options = options || {}; options = options || {};
@ -479,7 +536,10 @@
this.scrolling = false; this.scrolling = false;
this.scrollWhenOutside = options.scrollWhenOutside || false; this.scrollWhenOutside = options.scrollWhenOutside || false;
this.point = pointer(elements); var point = {}, pointCB = createPointCB(point), down = false;
window.addEventListener('mousemove', pointCB, false);
window.addEventListener('touchmove', pointCB, false);
if(!isNaN(options.pixels)){ if(!isNaN(options.pixels)){
pixels = options.pixels; pixels = options.pixels;
@ -494,12 +554,30 @@
} }
this.destroy = function() { this.destroy = function() {
this.point.destroy(); window.removeEventListener('mousemove', pointCB, false);
window.removeEventListener('touchmove', pointCB, false);
window.removeEventListener('mousedown', onDown, false);
window.removeEventListener('touchstart', onDown, false);
window.removeEventListener('mouseup', onUp, false);
window.removeEventListener('touchend', onUp, false);
}; };
var hasWindow = null, temp = [];
for(var i=0; i<elements.length; i++){
if(elements[i] === window){
hasWindow = window;
break;
}else{
temp.push(elements[i])
}
}
elements = temp;
temp = null;
Object.defineProperties(this, { Object.defineProperties(this, {
down: { down: {
get: function(){ return self.point.down; } get: function(){ return down; }
}, },
interval: { interval: {
get: function(){ return 1/pixels * 1000; } get: function(){ return 1/pixels * 1000; }
@ -510,48 +588,105 @@
} }
}); });
this.point.on('move', function(el, rect){ window.addEventListener('mousedown', onDown, false);
window.addEventListener('touchstart', onDown, false);
window.addEventListener('mouseup', onUp, false);
window.addEventListener('touchend', onUp, false);
function onDown(){
down = true;
}
function onUp(){
down = false;
}
var n = 0, current;
window.addEventListener('mousemove', onMove, false);
window.addEventListener('touchmove', onMove, false);
function onMove(event){
if(!el) return;
if(!self.autoScroll()) return; if(!self.autoScroll()) return;
if(!self.scrollWhenOutside && this.outside(el)) return; if(!event.target) return;
var target = event.target, last;
if(self.point.y < rect.top + self.margin){ if(!current || !inside(point, current)){
if(!current && target){
current = null;
while(target = target.parentNode){
for(var i=0; i<elements.length; i++){
if(elements[i] === target && inside(point, elements[i])){
current = elements[i];
break;
}
}
}
}else{
last = current;
current = null;
for(var i=0; i<elements.length; i++){
if(elements[i] !== last && inside(point, elements[i])){
current = elements[i];
}
}
}
}
if(hasWindow){
autoScroll(hasWindow);
}
if(!current) return;
autoScroll(current);
}
function autoScroll(el){
var rect = getRect(el);
if(point.y < rect.top + self.margin){
autoScrollV(el, -1, rect); autoScrollV(el, -1, rect);
}else if(self.point.y > rect.bottom - self.margin){ }else if(point.y > rect.bottom - self.margin){
autoScrollV(el, 1, rect); autoScrollV(el, 1, rect);
} }
if(self.point.x < rect.left + self.margin){ if(point.x < rect.left + self.margin){
autoScrollH(el, -1, rect); autoScrollH(el, -1, rect);
}else if(self.point.x > rect.right - self.margin){ }else if(point.x > rect.right - self.margin){
autoScrollH(el, 1, rect); autoScrollH(el, 1, rect);
} }
}); }
function autoScrollV(el, amount, rect){ function autoScrollV(el, amount, rect){
//if(!self.down) return;
if(!self.autoScroll()) return; if(!self.autoScroll()) return;
if(!self.scrollWhenOutside && self.point.outside(el)) return; if(!self.scrollWhenOutside && !inside(point, el, rect)) return;
if(el === window){ if(el === window){
window.scrollTo(el.pageXOffset, el.pageYOffset + amount); window.scrollTo(el.pageXOffset, el.pageYOffset + amount);
}else{ }else{
el.scrollTop = el.scrollTop + amount; el.scrollTop = el.scrollTop + amount;
} }
setTimeout(function(){ setTimeout(function(){
if(self.point.y < rect.top + self.margin){ if(point.y < rect.top + self.margin){
autoScrollV(el, amount, rect); autoScrollV(el, amount, rect);
}else if(self.point.y > rect.bottom - self.margin){ }else if(point.y > rect.bottom - self.margin){
autoScrollV(el, amount, rect); autoScrollV(el, amount, rect);
} }
}, self.interval); }, self.interval);
} }
function autoScrollH(el, amount, rect){ function autoScrollH(el, amount, rect){
//if(!self.down) return;
if(!self.autoScroll()) return; if(!self.autoScroll()) return;
if(!self.scrollWhenOutside && self.point.outside(el)) return; if(!self.scrollWhenOutside && !inside(point, el, rect)) return;
if(el === window){ if(el === window){
window.scrollTo(el.pageXOffset + amount, el.pageYOffset); window.scrollTo(el.pageXOffset + amount, el.pageYOffset);
}else{ }else{
@ -559,9 +694,9 @@
} }
setTimeout(function(){ setTimeout(function(){
if(self.point.x < rect.left + self.margin){ if(point.x < rect.left + self.margin){
autoScrollH(el, amount, rect); autoScrollH(el, amount, rect);
}else if(self.point.x > rect.right - self.margin){ }else if(point.x > rect.right - self.margin){
autoScrollH(el, amount, rect); autoScrollH(el, amount, rect);
} }
}, self.interval); }, self.interval);
@ -569,5 +704,36 @@
} }
function getRect(el){
if(el === window){
return {
top: 0,
left: 0,
right: window.innerWidth,
bottom: window.innerHeight,
width: window.innerWidth,
height: window.innerHeight
};
}else{
try{
return el.getBoundingClientRect();
}catch(e){
throw new TypeError("Can't call getBoundingClientRect on "+el);
}
}
}
function inside(point, el, rect){
rect = rect || getRect(el);
return (point.y > rect.top && point.y < rect.bottom &&
point.x > rect.left && point.x < rect.right);
}
function AutoScrollerFactory(element, options){
return new AutoScroller(element, options);
}
window.autoScroll = AutoScrollerFactory; window.autoScroll = AutoScrollerFactory;
}()); }());

View File

@ -2,6 +2,7 @@
var multipleSortableClass = 'ui-multisortable-multiple'; var multipleSortableClass = 'ui-multisortable-multiple';
var mainClass = 'main-drag-item'; var mainClass = 'main-drag-item';
var inProgress = false; var inProgress = false;
var removeEventFn = null;
var reset = function(elm) { var reset = function(elm) {
$(elm) $(elm)
@ -59,7 +60,7 @@
var current = dragMultiple.items.elm; var current = dragMultiple.items.elm;
var container = dragMultiple.items.container; var container = dragMultiple.items.container;
$(window).off('mousemove.dragmultiple'); document.documentElement.removeEventListener('mousemove', removeEventFn);
// reset // reset
dragMultiple.items = {}; dragMultiple.items = {};
@ -199,12 +200,14 @@
dragMultiple.start = function(item, container) { dragMultiple.start = function(item, container) {
if (isMultiple(item, container)) { if (isMultiple(item, container)) {
$(window).on('mousemove.dragmultiple', function() { document.documentElement.addEventListener('mousemove', function() {
if (!inProgress) { if (!inProgress) {
dragMultiple.prepare(item, container); dragMultiple.prepare(item, container);
} }
drag(); drag();
removeEventFn = arguments.callee;
}); });
} }
}; };

View File

@ -35,6 +35,8 @@
"ONE_ITEM_LINE": "In item per línia", "ONE_ITEM_LINE": "In item per línia",
"NEW_BULK": "Nova inserció en grup", "NEW_BULK": "Nova inserció en grup",
"RELATED_TASKS": "Tasques relacionades", "RELATED_TASKS": "Tasques relacionades",
"PREVIOUS": "Previous",
"NEXT": "Següent",
"LOGOUT": "Surt", "LOGOUT": "Surt",
"EXTERNAL_USER": "un usuari extern", "EXTERNAL_USER": "un usuari extern",
"GENERIC_ERROR": "Un Oompa Loompas diu {{error}}.", "GENERIC_ERROR": "Un Oompa Loompas diu {{error}}.",
@ -45,6 +47,11 @@
"CAPSLOCK_WARNING": "Be careful! You are using capital letters in an input field that is case sensitive.", "CAPSLOCK_WARNING": "Be careful! You are using capital letters in an input field that is case sensitive.",
"CONFIRM_CLOSE_EDIT_MODE_TITLE": "Are you sure you want to close the edit mode?", "CONFIRM_CLOSE_EDIT_MODE_TITLE": "Are you sure you want to close the edit mode?",
"CONFIRM_CLOSE_EDIT_MODE_MESSAGE": "Remember that if you close the edit mode without saving all the changes will be lost", "CONFIRM_CLOSE_EDIT_MODE_MESSAGE": "Remember that if you close the edit mode without saving all the changes will be lost",
"RELATED_USERSTORIES": "Related user stories",
"CARD": {
"ASSIGN_TO": "Assign To",
"EDIT": "Edit card"
},
"FORM_ERRORS": { "FORM_ERRORS": {
"DEFAULT_MESSAGE": "Aquest valor pareix invàlid.", "DEFAULT_MESSAGE": "Aquest valor pareix invàlid.",
"TYPE_EMAIL": "Deu ser un correu vàlid.", "TYPE_EMAIL": "Deu ser un correu vàlid.",
@ -115,8 +122,9 @@
"USER_STORY": "Història d'usuari", "USER_STORY": "Història d'usuari",
"TASK": "Tasca", "TASK": "Tasca",
"ISSUE": "incidència", "ISSUE": "incidència",
"EPIC": "Epic",
"TAGS": { "TAGS": {
"PLACEHOLDER": "Afegir tag", "PLACEHOLDER": "Enter tag",
"DELETE": "Elimina l'etiqueta", "DELETE": "Elimina l'etiqueta",
"ADD": "Afegeix l'etiqueta" "ADD": "Afegeix l'etiqueta"
}, },
@ -193,12 +201,29 @@
"CONFIRM_DELETE": "Remeber that all values in this custom field will be deleted.\n Are you sure you want to continue?" "CONFIRM_DELETE": "Remeber that all values in this custom field will be deleted.\n Are you sure you want to continue?"
}, },
"FILTERS": { "FILTERS": {
"TITLE": "filtres", "TITLE": "Filtres",
"INPUT_PLACEHOLDER": "Descripció o referència", "INPUT_PLACEHOLDER": "Descripció o referència",
"TITLE_ACTION_FILTER_BUTTON": "cerca", "TITLE_ACTION_FILTER_BUTTON": "cerca",
"BREADCRUMB_TITLE": "tornar a categories", "INPUT_SEARCH_PLACEHOLDER": "Descripció o ref",
"BREADCRUMB_FILTERS": "Filtres", "TITLE_ACTION_SEARCH": "Cerca",
"BREADCRUMB_STATUS": "estats" "ACTION_SAVE_CUSTOM_FILTER": "Guarda com a filtre",
"PLACEHOLDER_FILTER_NAME": "Escriu el filtre i pressiona Intro",
"APPLIED_FILTERS_NUM": "filters applied",
"CATEGORIES": {
"TYPE": "Tipus",
"STATUS": "Estats",
"SEVERITY": "Severitat",
"PRIORITIES": "Prioritats",
"TAGS": "Etiquetes",
"ASSIGNED_TO": "Assignat a",
"CREATED_BY": "Creat per",
"CUSTOM_FILTERS": "Filtres personalitzats",
"EPIC": "Epic"
},
"CONFIRM_DELETE": {
"TITLE": "Esborrar filtre",
"MESSAGE": "el filtre '{{customFilterName}}'"
}
}, },
"WYSIWYG": { "WYSIWYG": {
"H1_BUTTON": "Capçcalera de primer nivel", "H1_BUTTON": "Capçcalera de primer nivel",
@ -228,9 +253,18 @@
"PREVIEW_BUTTON": "Previsualitzar", "PREVIEW_BUTTON": "Previsualitzar",
"EDIT_BUTTON": "Editar", "EDIT_BUTTON": "Editar",
"ATTACH_FILE_HELP": "Attach files by dragging & dropping on the textarea above.", "ATTACH_FILE_HELP": "Attach files by dragging & dropping on the textarea above.",
"ATTACH_FILE_HELP_SAVE_FIRST": "Save first before if you want to attach files by dragging & dropping on the textarea above.",
"MARKDOWN_HELP": "Ajuda de Markdown" "MARKDOWN_HELP": "Ajuda de Markdown"
}, },
"PERMISIONS_CATEGORIES": { "PERMISIONS_CATEGORIES": {
"EPICS": {
"NAME": "Epics",
"VIEW_EPICS": "View epics",
"ADD_EPICS": "Add epics",
"MODIFY_EPICS": "Modify epics",
"COMMENT_EPICS": "Comment epics",
"DELETE_EPICS": "Delete epics"
},
"SPRINTS": { "SPRINTS": {
"NAME": "Sprints", "NAME": "Sprints",
"VIEW_SPRINTS": "Vore sprints", "VIEW_SPRINTS": "Vore sprints",
@ -243,6 +277,7 @@
"VIEW_USER_STORIES": "Vore istòries d'usuari", "VIEW_USER_STORIES": "Vore istòries d'usuari",
"ADD_USER_STORIES": "Afegir històries d'usuari", "ADD_USER_STORIES": "Afegir històries d'usuari",
"MODIFY_USER_STORIES": "Editar història d'usuari", "MODIFY_USER_STORIES": "Editar història d'usuari",
"COMMENT_USER_STORIES": "Comment user stories",
"DELETE_USER_STORIES": "Esborrar històries d'usuari" "DELETE_USER_STORIES": "Esborrar històries d'usuari"
}, },
"TASKS": { "TASKS": {
@ -250,6 +285,7 @@
"VIEW_TASKS": "Vore tasca", "VIEW_TASKS": "Vore tasca",
"ADD_TASKS": "Afegit tasques", "ADD_TASKS": "Afegit tasques",
"MODIFY_TASKS": "Modificar tasques", "MODIFY_TASKS": "Modificar tasques",
"COMMENT_TASKS": "Comment tasks",
"DELETE_TASKS": "Esborrar tasques" "DELETE_TASKS": "Esborrar tasques"
}, },
"ISSUES": { "ISSUES": {
@ -257,6 +293,7 @@
"VIEW_ISSUES": "Vore incidències", "VIEW_ISSUES": "Vore incidències",
"ADD_ISSUES": "Afegeix incidències", "ADD_ISSUES": "Afegeix incidències",
"MODIFY_ISSUES": "Modifica incidències", "MODIFY_ISSUES": "Modifica incidències",
"COMMENT_ISSUES": "Comment issues",
"DELETE_ISSUES": "Elimina incidències" "DELETE_ISSUES": "Elimina incidències"
}, },
"WIKI": { "WIKI": {
@ -366,6 +403,41 @@
"WATCHING_SECTION": "Observant", "WATCHING_SECTION": "Observant",
"DASHBOARD": "Panell principal" "DASHBOARD": "Panell principal"
}, },
"EPICS": {
"TITLE": "EPICS",
"SECTION_NAME": "Epics",
"EPIC": "EPIC",
"PAGE_TITLE": "Epics - {{projectName}}",
"PAGE_DESCRIPTION": "The epics list of the project {{projectName}}: {{projectDescription}}",
"DASHBOARD": {
"ADD": "+ ADD EPIC",
"UNASSIGNED": "Sense assignar"
},
"EMPTY": {
"TITLE": "It looks like there aren't any epics yet",
"EXPLANATION": "Epics are items at a higher level that encompass user stories.<br />Epics are at the top of the hierarchy and can be used to group user stories together.",
"HELP": "Learn more about epics"
},
"TABLE": {
"VOTES": "Vots",
"NAME": "Nom",
"PROJECT": "Projecte",
"SPRINT": "Sprint",
"ASSIGNED_TO": "Assigned",
"STATUS": "Estats",
"PROGRESS": "Progress",
"VIEW_OPTIONS": "View options"
},
"CREATE": {
"TITLE": "New Epic",
"PLACEHOLDER_DESCRIPTION": "Please add descriptive text to help others better understand this epic",
"TEAM_REQUIREMENT": "Team requirement",
"CLIENT_REQUIREMENT": "Client requirement",
"BLOCKED": "Bloquejat",
"BLOCKED_NOTE_PLACEHOLDER": "Why is this epic blocked?",
"CREATE_EPIC": "Create epic"
}
},
"PROJECTS": { "PROJECTS": {
"PAGE_TITLE": "Els meus projectes - Taiga", "PAGE_TITLE": "Els meus projectes - Taiga",
"PAGE_DESCRIPTION": "Una llista de tots els teus projects, que pots reordenar o crear nous.", "PAGE_DESCRIPTION": "Una llista de tots els teus projects, que pots reordenar o crear nous.",
@ -402,7 +474,8 @@
"ADMIN": { "ADMIN": {
"COMMON": { "COMMON": {
"TITLE_ACTION_EDIT_VALUE": "Editar valor", "TITLE_ACTION_EDIT_VALUE": "Editar valor",
"TITLE_ACTION_DELETE_VALUE": "Borrar valor" "TITLE_ACTION_DELETE_VALUE": "Borrar valor",
"TITLE_ACTION_DELETE_TAG": "Elimina l'etiqueta"
}, },
"HELP": "Necessites ajuda? Mira la nosta pàgina de suport!", "HELP": "Necessites ajuda? Mira la nosta pàgina de suport!",
"PROJECT_DEFAULT_VALUES": { "PROJECT_DEFAULT_VALUES": {
@ -435,6 +508,8 @@
"TITLE": "Mòdules", "TITLE": "Mòdules",
"ENABLE": "Activa", "ENABLE": "Activa",
"DISABLE": "Desactiva", "DISABLE": "Desactiva",
"EPICS": "Epics",
"EPICS_DESCRIPTION": "Visualize and manage the most strategic part of your project",
"BACKLOG": "Backlog", "BACKLOG": "Backlog",
"BACKLOG_DESCRIPTION": "Organitza les històries d'usuari per a mantindre una vista organitzada i prioritzada del treball.", "BACKLOG_DESCRIPTION": "Organitza les històries d'usuari per a mantindre una vista organitzada i prioritzada del treball.",
"NUMBER_SPRINTS": "Expected number of sprints", "NUMBER_SPRINTS": "Expected number of sprints",
@ -471,9 +546,9 @@
"PRIVATE_PROJECT": "Projecte privat", "PRIVATE_PROJECT": "Projecte privat",
"PRIVATE_OR_PUBLIC": "What's the difference between public and private projects?", "PRIVATE_OR_PUBLIC": "What's the difference between public and private projects?",
"DELETE": "Esborra aquest projecte", "DELETE": "Esborra aquest projecte",
"LOGO_HELP": "The image will be scaled to 80x80px.", "LOGO_HELP": "S'escalarà la imatge a 80x80px.",
"CHANGE_LOGO": "Change logo", "CHANGE_LOGO": "Change logo",
"ACTION_USE_DEFAULT_LOGO": "Use default image", "ACTION_USE_DEFAULT_LOGO": "Utilitza la imatge per defecte",
"MAX_PRIVATE_PROJECTS": "You've reached the maximum number of private projects allowed by your current plan", "MAX_PRIVATE_PROJECTS": "You've reached the maximum number of private projects allowed by your current plan",
"MAX_PRIVATE_PROJECTS_MEMBERS": "The maximum number of members for private projects has been exceeded", "MAX_PRIVATE_PROJECTS_MEMBERS": "The maximum number of members for private projects has been exceeded",
"MAX_PUBLIC_PROJECTS": "Unfortunately, you've reached the maximum number of public projects allowed by your current plan", "MAX_PUBLIC_PROJECTS": "Unfortunately, you've reached the maximum number of public projects allowed by your current plan",
@ -497,6 +572,7 @@
"REGENERATE_SUBTITLE": "Vas a canviar la URL d'accés al CSV. La URL previa no funcionarà. Estàs segur?" "REGENERATE_SUBTITLE": "Vas a canviar la URL d'accés al CSV. La URL previa no funcionarà. Estàs segur?"
}, },
"CSV": { "CSV": {
"SECTION_TITLE_EPIC": "epics reports",
"SECTION_TITLE_US": "informes d'històries d'usuari", "SECTION_TITLE_US": "informes d'històries d'usuari",
"SECTION_TITLE_TASK": "infome de tasques", "SECTION_TITLE_TASK": "infome de tasques",
"SECTION_TITLE_ISSUE": "informe d'incidències", "SECTION_TITLE_ISSUE": "informe d'incidències",
@ -509,6 +585,8 @@
"CUSTOM_FIELDS": { "CUSTOM_FIELDS": {
"TITLE": "Camps personalitzats", "TITLE": "Camps personalitzats",
"SUBTITLE": "Especifiqueu els camps personalitzats del les vostres històries d'usuari, tasques i incidències", "SUBTITLE": "Especifiqueu els camps personalitzats del les vostres històries d'usuari, tasques i incidències",
"EPIC_DESCRIPTION": "Epics custom fields",
"EPIC_ADD": "Add a custom field in epics",
"US_DESCRIPTION": "Camps personalitzats d'històries d'usuari", "US_DESCRIPTION": "Camps personalitzats d'històries d'usuari",
"US_ADD": "Afegeix camps personalitzats en històries d'usuari", "US_ADD": "Afegeix camps personalitzats en històries d'usuari",
"TASK_DESCRIPTION": "Camps personalitzats de tasques", "TASK_DESCRIPTION": "Camps personalitzats de tasques",
@ -546,7 +624,8 @@
"PROJECT_VALUES_STATUS": { "PROJECT_VALUES_STATUS": {
"TITLE": "Estat", "TITLE": "Estat",
"SUBTITLE": "Especifica els estats de les vostres històries d'usuari, tasques i incidències", "SUBTITLE": "Especifica els estats de les vostres històries d'usuari, tasques i incidències",
"US_TITLE": "Estats d'US", "EPIC_TITLE": "Epic Statuses",
"US_TITLE": "User Story Statuses",
"TASK_TITLE": "Estats de tasques", "TASK_TITLE": "Estats de tasques",
"ISSUE_TITLE": "Estats d'incidències" "ISSUE_TITLE": "Estats d'incidències"
}, },
@ -556,6 +635,17 @@
"ISSUE_TITLE": "Tipus d'incidències", "ISSUE_TITLE": "Tipus d'incidències",
"ACTION_ADD": "Afegir now {{objName}}" "ACTION_ADD": "Afegir now {{objName}}"
}, },
"PROJECT_VALUES_TAGS": {
"TITLE": "Etiquetes",
"SUBTITLE": "View and edit the color of your tags",
"EMPTY": "Currently there are no tags",
"EMPTY_SEARCH": "It looks like nothing was found with your search criteria",
"ACTION_ADD": "Afegeix l'etiqueta",
"NEW_TAG": "New tag",
"MIXING_HELP_TEXT": "Select the tags that you want to merge",
"MIXING_MERGE": "Merge Tags",
"SELECTED": "Selected"
},
"ROLES": { "ROLES": {
"PAGE_TITLE": "Rols - {{projectName}}", "PAGE_TITLE": "Rols - {{projectName}}",
"WARNING_NO_ROLE": "Ves amb compte, cap rol en el teu projecte pot estimar punts per a les històries d'usuari", "WARNING_NO_ROLE": "Ves amb compte, cap rol en el teu projecte pot estimar punts per a les històries d'usuari",
@ -588,6 +678,10 @@
"SECTION_NAME": "Github", "SECTION_NAME": "Github",
"PAGE_TITLE": "Github - {{projectName}}" "PAGE_TITLE": "Github - {{projectName}}"
}, },
"GOGS": {
"SECTION_NAME": "Gogs",
"PAGE_TITLE": "Gogs - {{projectName}}"
},
"WEBHOOKS": { "WEBHOOKS": {
"PAGE_TITLE": "Webhooks - {{projectName}}", "PAGE_TITLE": "Webhooks - {{projectName}}",
"SECTION_NAME": "Webhooks", "SECTION_NAME": "Webhooks",
@ -643,13 +737,14 @@
"DEFAULT_DELETE_MESSAGE": "la invitació a '{{email}}'." "DEFAULT_DELETE_MESSAGE": "la invitació a '{{email}}'."
}, },
"DEFAULT_VALUES": { "DEFAULT_VALUES": {
"LABEL_EPIC_STATUS": "Default value for epic status selector",
"LABEL_US_STATUS": "Default value for user story status selector",
"LABEL_POINTS": "Valor per defecte per a selector de punts", "LABEL_POINTS": "Valor per defecte per a selector de punts",
"LABEL_US": "Valor per defecte per a selector d'estats d'US",
"LABEL_TASK_STATUS": "Valor per defecte per a selector d'estats de tasques", "LABEL_TASK_STATUS": "Valor per defecte per a selector d'estats de tasques",
"LABEL_PRIORITY": "Valor per defecte per a selector de prioritat",
"LABEL_SEVERITY": "Valor per defecte per a selector de severitat",
"LABEL_ISSUE_TYPE": "Valor per defecte per a selector de tipus", "LABEL_ISSUE_TYPE": "Valor per defecte per a selector de tipus",
"LABEL_ISSUE_STATUS": "Valor per defecte per a selector de estats" "LABEL_ISSUE_STATUS": "Valor per defecte per a selector de estats",
"LABEL_PRIORITY": "Valor per defecte per a selector de prioritat",
"LABEL_SEVERITY": "Valor per defecte per a selector de severitat"
}, },
"STATUS": { "STATUS": {
"PLACEHOLDER_WRITE_STATUS_NAME": "Escriu un nom per a nou estat" "PLACEHOLDER_WRITE_STATUS_NAME": "Escriu un nom per a nou estat"
@ -681,7 +776,8 @@
"PRIORITIES": "Prioritats", "PRIORITIES": "Prioritats",
"SEVERITIES": "severitats", "SEVERITIES": "severitats",
"TYPES": "Tipus", "TYPES": "Tipus",
"CUSTOM_FIELDS": "Camps personalitzats" "CUSTOM_FIELDS": "Camps personalitzats",
"TAGS": "Etiquetes"
}, },
"SUBMENU_PROJECT_PROFILE": { "SUBMENU_PROJECT_PROFILE": {
"TITLE": "Perfil de projecte" "TITLE": "Perfil de projecte"
@ -751,6 +847,8 @@
"FILTER_TYPE_ALL_TITLE": "Mostrar tot", "FILTER_TYPE_ALL_TITLE": "Mostrar tot",
"FILTER_TYPE_PROJECTS": "Projectes", "FILTER_TYPE_PROJECTS": "Projectes",
"FILTER_TYPE_PROJECT_TITLES": "Mostra només projectes", "FILTER_TYPE_PROJECT_TITLES": "Mostra només projectes",
"FILTER_TYPE_EPICS": "Epics",
"FILTER_TYPE_EPIC_TITLES": "Show only epics",
"FILTER_TYPE_USER_STORIES": "Históries", "FILTER_TYPE_USER_STORIES": "Históries",
"FILTER_TYPE_USER_STORIES_TITLES": "Veure només històries d'usuari", "FILTER_TYPE_USER_STORIES_TITLES": "Veure només històries d'usuari",
"FILTER_TYPE_TASKS": "Tasques", "FILTER_TYPE_TASKS": "Tasques",
@ -821,7 +919,7 @@
"CHANGE_PASSWORD": "Canvi de contrasenya", "CHANGE_PASSWORD": "Canvi de contrasenya",
"DASHBOARD_TITLE": "Tauler", "DASHBOARD_TITLE": "Tauler",
"DISCOVER_TITLE": "Discover trending projects", "DISCOVER_TITLE": "Discover trending projects",
"NEW_ITEM": "New", "NEW_ITEM": "Nova",
"DISCOVER": "Descobreix", "DISCOVER": "Descobreix",
"ACTION_REORDER": "Arrossega els elements per endreçar" "ACTION_REORDER": "Arrossega els elements per endreçar"
}, },
@ -950,8 +1048,8 @@
"CREATE_MEMBER": { "CREATE_MEMBER": {
"PLACEHOLDER_INVITATION_TEXT": "(Opcional) Afegix un text personalizat a la invitació. Dis-li algo divertit als nous membres. ;-)", "PLACEHOLDER_INVITATION_TEXT": "(Opcional) Afegix un text personalizat a la invitació. Dis-li algo divertit als nous membres. ;-)",
"PLACEHOLDER_TYPE_EMAIL": "Escriu un correu", "PLACEHOLDER_TYPE_EMAIL": "Escriu un correu",
"LIMIT_USERS_WARNING_MESSAGE_FOR_OWNER": "Unfortunately, this project can't have more than <strong>{{maxMembers}}</strong> members.<br> If you would like to increase the current limit, please contact the administrator.", "LIMIT_USERS_WARNING_MESSAGE_FOR_OWNER": "You are about to reach the maximum number of members allowed for this project, <strong>{{maxMembers}}</strong> members. If you would like to increase the current limit, please contact the administrator.",
"LIMIT_USERS_WARNING_MESSAGE": "Unfortunately, this project can't have more than <strong>{{maxMembers}}</strong> members." "LIMIT_USERS_WARNING_MESSAGE": "You are about to reach the maximum number of members allowed for this project, <strong>{{maxMembers}}</strong> members."
}, },
"LEAVE_PROJECT_WARNING": { "LEAVE_PROJECT_WARNING": {
"TITLE": "Unfortunately, this project can't be left without an owner", "TITLE": "Unfortunately, this project can't be left without an owner",
@ -970,10 +1068,30 @@
"BUTTON": "Ask this project member to become the new project owner" "BUTTON": "Ask this project member to become the new project owner"
} }
}, },
"EPIC": {
"PAGE_TITLE": "{{epicSubject}} - Epic {{epicRef}} - {{projectName}}",
"PAGE_DESCRIPTION": "Status: {{epicStatus }}. Description: {{epicDescription}}",
"SECTION_NAME": "Epic",
"TITLE_LIGHTBOX_UNLINK_RELATED_USERSTORY": "Unlink related userstory",
"MSG_LIGHTBOX_UNLINK_RELATED_USERSTORY": "It will delete the link to the related userstory '{{subject}}'",
"ERROR_UNLINK_RELATED_USERSTORY": "We have not been able to unlink: {{errorMessage}}",
"CREATE_RELATED_USERSTORIES": "Create a relationship with",
"NEW_USERSTORY": "Nova història d'usuari",
"EXISTING_USERSTORY": "Existing user story",
"CHOOSE_PROJECT_FOR_CREATION": "What's the project?",
"SUBJECT": "Descripció",
"SUBJECT_BULK_MODE": "Subject (bulk insert)",
"CHOOSE_PROJECT_FROM": "What's the project?",
"CHOOSE_USERSTORY": "What's the user story?",
"NO_USERSTORIES": "This project has no User Stories yet. Please select another project.",
"FILTER_USERSTORIES": "Filter user stories",
"LIGHTBOX_TITLE_BLOKING_EPIC": "Blocking epic",
"ACTION_DELETE": "Delete epic"
},
"US": { "US": {
"PAGE_TITLE": "{{userStorySubject}} - Història d'Usuari {{userStoryRef}} - {{projectName}}", "PAGE_TITLE": "{{userStorySubject}} - Història d'Usuari {{userStoryRef}} - {{projectName}}",
"PAGE_DESCRIPTION": "Estat: {{userStoryStatus }}. Completat {{userStoryProgressPercentage}}% ({{userStoryClosedTasks}} de {{userStoryTotalTasks}} tasques tancades). Punts: {{userStoryPoints}}. Descripció: {{userStoryDescription}}", "PAGE_DESCRIPTION": "Estat: {{userStoryStatus }}. Completat {{userStoryProgressPercentage}}% ({{userStoryClosedTasks}} de {{userStoryTotalTasks}} tasques tancades). Punts: {{userStoryPoints}}. Descripció: {{userStoryDescription}}",
"SECTION_NAME": "Detalls de la història d'usuari", "SECTION_NAME": "Història d'usuari",
"LINK_TASKBOARD": "Panell de tasques", "LINK_TASKBOARD": "Panell de tasques",
"TITLE_LINK_TASKBOARD": "Anar a panell de tasques", "TITLE_LINK_TASKBOARD": "Anar a panell de tasques",
"TOTAL_POINTS": "punts totals", "TOTAL_POINTS": "punts totals",
@ -984,14 +1102,23 @@
"EXTERNAL_REFERENCE": "Aquesta US ha sigut creada desde", "EXTERNAL_REFERENCE": "Aquesta US ha sigut creada desde",
"GO_TO_EXTERNAL_REFERENCE": "Anar a l'orige", "GO_TO_EXTERNAL_REFERENCE": "Anar a l'orige",
"BLOCKED": "Aquest història d'usuari està bloquejada", "BLOCKED": "Aquest història d'usuari està bloquejada",
"PREVIOUS": "previa història d'usuari",
"NEXT": "Pròxima història d'usuari",
"TITLE_DELETE_ACTION": "Esborra història d'usuari", "TITLE_DELETE_ACTION": "Esborra història d'usuari",
"LIGHTBOX_TITLE_BLOKING_US": "Bloquejant US", "LIGHTBOX_TITLE_BLOKING_US": "Bloquejant US",
"TASK_COMPLETED": "{{totalClosedTasks}}/{{totalTasks}} tasques completades", "TASK_COMPLETED": "{{totalClosedTasks}}/{{totalTasks}} tasques completades",
"ASSIGN": "Assigna història d'usuari", "ASSIGN": "Assigna història d'usuari",
"NOT_ESTIMATED": "Sense estimar", "NOT_ESTIMATED": "Sense estimar",
"TOTAL_US_POINTS": "Punts totals d'US", "TOTAL_US_POINTS": "Punts totals d'US",
"TRIBE": {
"PUBLISH": "Publish as Gig in Taiga Tribe",
"PUBLISH_INFO": "More info",
"PUBLISH_TITLE": "More info on publishing in Taiga Tribe",
"PUBLISHED_AS_GIG": "Story published as Gig in Taiga Tribe",
"EDIT_LINK": "Edit link",
"CLOSE": "Close",
"SYNCHRONIZE_LINK": "synchronize with Taiga Tribe",
"PUBLISH_MORE_INFO_TITLE": "Do you need somebody for this task?",
"PUBLISH_MORE_INFO_TEXT": "<p>If you need help with a particular piece of work you can easily create gigs on<a href='taigatribe.com' title='Taiga Tribe'> Taiga Tribe </a> and receive help from all over the world. You will be able to control and manage the gig enjoying a great community eager to contribute.</p><p><a href='taigatribe.com' title='Taiga Tribe'> TaigaTribe </a> was born as a Taiga sibling. Both platforms can live separately but we believe that there is much power in using them combined so we are making sure the integration works like a charm.</p>"
},
"FIELDS": { "FIELDS": {
"TEAM_REQUIREMENT": "Requeriment d'equip", "TEAM_REQUIREMENT": "Requeriment d'equip",
"CLIENT_REQUIREMENT": "Requeriment de client", "CLIENT_REQUIREMENT": "Requeriment de client",
@ -999,28 +1126,47 @@
} }
}, },
"COMMENTS": { "COMMENTS": {
"DELETED_INFO": "Comentari esborrat per {{user}} el {{date}}", "DELETED_INFO": "Comment deleted by {{user}}",
"TITLE": "Comentaris", "TITLE": "Comentaris",
"COMMENTS_COUNT": "{{comments}} Comments",
"ORDER": "Order",
"OLDER_FIRST": "Older first",
"RECENT_FIRST": "Recent first",
"COMMENT": "Comentar", "COMMENT": "Comentar",
"EDIT_COMMENT": "Edit comment",
"EDITED_COMMENT": "Edited:",
"SHOW_HISTORY": "View historic",
"TYPE_NEW_COMMENT": "Escriu un nou comentari ací", "TYPE_NEW_COMMENT": "Escriu un nou comentari ací",
"SHOW_DELETED": "Mostra el comentari esborrat.", "SHOW_DELETED": "Mostra el comentari esborrat.",
"HIDE_DELETED": "Amaga el comentari esborrat", "HIDE_DELETED": "Amaga el comentari esborrat",
"DELETE": "Esborrar comentari", "DELETE": "Esborrar comentari",
"RESTORE": "Resturar comentari." "RESTORE": "Resturar comentari.",
"HISTORY": {
"TITLE": "Activitat"
}
}, },
"ACTIVITY": { "ACTIVITY": {
"SHOW_ACTIVITY": "Mostrar activitat", "SHOW_ACTIVITY": "Mostrar activitat",
"DATETIME": "DD MMM YYYY HH:mm", "DATETIME": "DD MMM YYYY HH:mm",
"SHOW_MORE": "+ Mostrar activitat anterior ({{showMore}} més)", "SHOW_MORE": "+ Mostrar activitat anterior ({{showMore}} més)",
"TITLE": "Activitat", "TITLE": "Activitat",
"ACTIVITIES_COUNT": "{{activities}} Activities",
"REMOVED": "Borrat", "REMOVED": "Borrat",
"ADDED": "Afegit", "ADDED": "Afegit",
"US_POINTS": "Punts d'US ({{name}})", "TAGS_ADDED": "tags added:",
"NEW_ATTACHMENT": "Nou adjunt", "TAGS_REMOVED": "tags removed:",
"DELETED_ATTACHMENT": "Adjunts esborrats", "US_POINTS": "{{role}} points",
"UPDATED_ATTACHMENT": "Actualitzat adjunt {{filename}}", "NEW_ATTACHMENT": "new attachment:",
"DELETED_CUSTOM_ATTRIBUTE": "Esborrar camps personalitzat", "DELETED_ATTACHMENT": "deleted attachment:",
"UPDATED_ATTACHMENT": "updated attachment ({{filename}}):",
"CREATED_CUSTOM_ATTRIBUTE": "created custom attribute",
"UPDATED_CUSTOM_ATTRIBUTE": "updated custom attribute",
"SIZE_CHANGE": "Fet {size, plural, one{un canvi} other{# changes}}", "SIZE_CHANGE": "Fet {size, plural, one{un canvi} other{# changes}}",
"BECAME_DEPRECATED": "became deprecated",
"BECAME_UNDEPRECATED": "became undeprecated",
"TEAM_REQUIREMENT": "Requeriment d'equip",
"CLIENT_REQUIREMENT": "Requeriment de client",
"BLOCKED": "Bloquejat",
"VALUES": { "VALUES": {
"YES": "si", "YES": "si",
"NO": "no", "NO": "no",
@ -1052,12 +1198,14 @@
"TAGS": "Etiquetes", "TAGS": "Etiquetes",
"ATTACHMENTS": "adjunts", "ATTACHMENTS": "adjunts",
"IS_DEPRECATED": "és obsolet", "IS_DEPRECATED": "és obsolet",
"IS_NOT_DEPRECATED": "is not deprecated",
"ORDER": "ordre", "ORDER": "ordre",
"BACKLOG_ORDER": "ordre de backlog", "BACKLOG_ORDER": "ordre de backlog",
"SPRINT_ORDER": "ordre d'sprint", "SPRINT_ORDER": "ordre d'sprint",
"KANBAN_ORDER": "ordre de kanban", "KANBAN_ORDER": "ordre de kanban",
"TASKBOARD_ORDER": "ordre de panell de tasques", "TASKBOARD_ORDER": "ordre de panell de tasques",
"US_ORDER": "ordre d'US" "US_ORDER": "ordre d'US",
"COLOR": "color"
} }
}, },
"BACKLOG": { "BACKLOG": {
@ -1109,7 +1257,8 @@
"CLOSED_TASKS": "tasques<br />tancades", "CLOSED_TASKS": "tasques<br />tancades",
"IOCAINE_DOSES": "dosis<br />iocaína", "IOCAINE_DOSES": "dosis<br />iocaína",
"SHOW_STATISTICS_TITLE": "Mostrar estadístiques", "SHOW_STATISTICS_TITLE": "Mostrar estadístiques",
"TOGGLE_BAKLOG_GRAPH": "Show/Hide burndown graph" "TOGGLE_BAKLOG_GRAPH": "Show/Hide burndown graph",
"POINTS_PER_ROLE": "Points per role"
}, },
"SUMMARY": { "SUMMARY": {
"PROJECT_POINTS": "punts<br/> projecte", "PROJECT_POINTS": "punts<br/> projecte",
@ -1122,9 +1271,7 @@
"TITLE": "Filtres", "TITLE": "Filtres",
"REMOVE": "Esborra filtres", "REMOVE": "Esborra filtres",
"HIDE": "Amaga filtres", "HIDE": "Amaga filtres",
"SHOW": "Mostra filtres", "SHOW": "Mostra filtres"
"FILTER_CATEGORY_STATUS": "Estats",
"FILTER_CATEGORY_TAGS": "Etiquetes"
}, },
"SPRINTS": { "SPRINTS": {
"TITLE": "SPRINTS", "TITLE": "SPRINTS",
@ -1179,7 +1326,7 @@
"TASK": { "TASK": {
"PAGE_TITLE": "{{taskSubject}} - Tasca {{taskRef}} - {{projectName}}", "PAGE_TITLE": "{{taskSubject}} - Tasca {{taskRef}} - {{projectName}}",
"PAGE_DESCRIPTION": "Estat: {{taskStatus }}. Descripció: {{taskDescription}}", "PAGE_DESCRIPTION": "Estat: {{taskStatus }}. Descripció: {{taskDescription}}",
"SECTION_NAME": "Detalls de la tasca", "SECTION_NAME": "Tasca",
"LINK_TASKBOARD": "Panell de tasques", "LINK_TASKBOARD": "Panell de tasques",
"TITLE_LINK_TASKBOARD": "Anar a panell de tasques", "TITLE_LINK_TASKBOARD": "Anar a panell de tasques",
"PLACEHOLDER_SUBJECT": "Afegix la descripció de la tasca", "PLACEHOLDER_SUBJECT": "Afegix la descripció de la tasca",
@ -1189,8 +1336,6 @@
"ORIGIN_US": "Aquesta tasca ha sigut creada desde", "ORIGIN_US": "Aquesta tasca ha sigut creada desde",
"TITLE_LINK_GO_ORIGIN": "Anar a història d'usuari", "TITLE_LINK_GO_ORIGIN": "Anar a història d'usuari",
"BLOCKED": "Aquesta tasca està bloquejada", "BLOCKED": "Aquesta tasca està bloquejada",
"PREVIOUS": "tasca prèvia",
"NEXT": "pròxima tasca",
"TITLE_DELETE_ACTION": "Esborrar tasca", "TITLE_DELETE_ACTION": "Esborrar tasca",
"LIGHTBOX_TITLE_BLOKING_TASK": "Bloquejant tasca", "LIGHTBOX_TITLE_BLOKING_TASK": "Bloquejant tasca",
"FIELDS": { "FIELDS": {
@ -1228,16 +1373,13 @@
"PAGE_TITLE": "Incidències - {{projectName}}", "PAGE_TITLE": "Incidències - {{projectName}}",
"PAGE_DESCRIPTION": "El panell d'incidències de {{projectName}}: {{projectDescription}}", "PAGE_DESCRIPTION": "El panell d'incidències de {{projectName}}: {{projectDescription}}",
"LIST_SECTION_NAME": "Incidències", "LIST_SECTION_NAME": "Incidències",
"SECTION_NAME": "Detalls d'incidència", "SECTION_NAME": "incidència",
"ACTION_NEW_ISSUE": "+ NOVA INCIDÈNCIA", "ACTION_NEW_ISSUE": "+ NOVA INCIDÈNCIA",
"ACTION_PROMOTE_TO_US": "Promocionar història d'usuari", "ACTION_PROMOTE_TO_US": "Promocionar història d'usuari",
"PLACEHOLDER_FILTER_NAME": "Escriu el filtre i pressiona Intro",
"PROMOTED": "Esta incidència ha sigut promcionada a US:", "PROMOTED": "Esta incidència ha sigut promcionada a US:",
"EXTERNAL_REFERENCE": "Esta incidència ha sigut creada desde", "EXTERNAL_REFERENCE": "Esta incidència ha sigut creada desde",
"GO_TO_EXTERNAL_REFERENCE": "Anar a l'orige", "GO_TO_EXTERNAL_REFERENCE": "Anar a l'orige",
"BLOCKED": "Aquesta incidència està bloquejada", "BLOCKED": "Aquesta incidència està bloquejada",
"TITLE_PREVIOUS_ISSUE": "incidència prèvia",
"TITLE_NEXT_ISSUE": "pròxima incidència",
"ACTION_DELETE": "Esborrar incidència", "ACTION_DELETE": "Esborrar incidència",
"LIGHTBOX_TITLE_BLOKING_ISSUE": "Bloquejant incidència", "LIGHTBOX_TITLE_BLOKING_ISSUE": "Bloquejant incidència",
"FIELDS": { "FIELDS": {
@ -1249,28 +1391,6 @@
"TITLE": "Promociona aquesta incidència a història d'usuari", "TITLE": "Promociona aquesta incidència a història d'usuari",
"MESSAGE": "Segur que vols crear una nova US desde aquesta incidència" "MESSAGE": "Segur que vols crear una nova US desde aquesta incidència"
}, },
"FILTERS": {
"TITLE": "Filtres",
"INPUT_SEARCH_PLACEHOLDER": "Descripció o ref",
"TITLE_ACTION_SEARCH": "Busca",
"ACTION_SAVE_CUSTOM_FILTER": "Guarda com a filtre",
"BREADCRUMB": "Filtres",
"TITLE_BREADCRUMB": "Filtres",
"CATEGORIES": {
"TYPE": "Tipus",
"STATUS": "Estats",
"SEVERITY": "Severitat",
"PRIORITIES": "Prioritats",
"TAGS": "Etiquetes",
"ASSIGNED_TO": "Assignat a",
"CREATED_BY": "Creat per",
"CUSTOM_FILTERS": "Filtres personalitzats"
},
"CONFIRM_DELETE": {
"TITLE": "Esborrar filtre",
"MESSAGE": "el filtre '{{customFilterName}}'"
}
},
"TABLE": { "TABLE": {
"COLUMNS": { "COLUMNS": {
"TYPE": "Tipus", "TYPE": "Tipus",
@ -1316,6 +1436,7 @@
"SEARCH": { "SEARCH": {
"PAGE_TITLE": "Cerca - {{projectName}}", "PAGE_TITLE": "Cerca - {{projectName}}",
"PAGE_DESCRIPTION": "Busca qualsevol cosa al projecte {{projectName}}: {{projectDescription}}", "PAGE_DESCRIPTION": "Busca qualsevol cosa al projecte {{projectName}}: {{projectDescription}}",
"FILTER_EPICS": "Epics",
"FILTER_USER_STORIES": "Històries d'usuari", "FILTER_USER_STORIES": "Històries d'usuari",
"FILTER_ISSUES": "Incidències", "FILTER_ISSUES": "Incidències",
"FILTER_TASKS": "Tasca", "FILTER_TASKS": "Tasca",
@ -1375,9 +1496,9 @@
} }
}, },
"USER_PROFILE": { "USER_PROFILE": {
"IMAGE_HELP": "The image will be scaled to 80x80px.", "IMAGE_HELP": "S'escalarà la imatge a 80x80px.",
"ACTION_CHANGE_IMAGE": "Canviar", "ACTION_CHANGE_IMAGE": "Canviar",
"ACTION_USE_GRAVATAR": "Use default image", "ACTION_USE_GRAVATAR": "Utilitza la imatge per defecte",
"ACTION_DELETE_ACCOUNT": "Esborrar compte de Taiga", "ACTION_DELETE_ACCOUNT": "Esborrar compte de Taiga",
"CHANGE_EMAIL_SUCCESS": "<strong>Mira el teu correu!</strong><br />Hem enviat un correu al teu conter<br /> amb les instrucciones per a escriure una nova adreça de correu", "CHANGE_EMAIL_SUCCESS": "<strong>Mira el teu correu!</strong><br />Hem enviat un correu al teu conter<br /> amb les instrucciones per a escriure una nova adreça de correu",
"CHANGE_PHOTO": "Canviar foto", "CHANGE_PHOTO": "Canviar foto",
@ -1417,13 +1538,24 @@
"DELETE_LIGHTBOX_TITLE": "Esborrar pàgina de Wiki", "DELETE_LIGHTBOX_TITLE": "Esborrar pàgina de Wiki",
"DELETE_LINK_TITLE": "Delete Wiki link", "DELETE_LINK_TITLE": "Delete Wiki link",
"NAVIGATION": { "NAVIGATION": {
"SECTION_NAME": "Enllaços", "HOME": "Main Page",
"ACTION_ADD_LINK": "Afegir link" "SECTION_NAME": "BOOKMARKS",
"ACTION_ADD_LINK": "Add bookmark",
"ALL_PAGES": "All wiki pages"
}, },
"SUMMARY": { "SUMMARY": {
"TIMES_EDITED": "voltes <br />editat", "TIMES_EDITED": "voltes <br />editat",
"LAST_EDIT": "última <br />edició", "LAST_EDIT": "última <br />edició",
"LAST_MODIFICATION": "última modificació" "LAST_MODIFICATION": "última modificació"
},
"SECTION_PAGES_LIST": "All pages",
"PAGES_LIST_COLUMNS": {
"TITLE": "Title",
"EDITIONS": "Editions",
"CREATED": "Creat",
"MODIFIED": "Modified",
"CREATOR": "Creator",
"LAST_MODIFIER": "Last modifier"
} }
}, },
"HINTS": { "HINTS": {
@ -1447,6 +1579,8 @@
"TASK_CREATED_WITH_US": "{{username}} ha creat una nova tasca {{obj_name}} a {{project_name}} provinent de US {{us_name}}", "TASK_CREATED_WITH_US": "{{username}} ha creat una nova tasca {{obj_name}} a {{project_name}} provinent de US {{us_name}}",
"WIKI_CREATED": "{{username}} has created a new wiki page {{obj_name}} in {{project_name}}", "WIKI_CREATED": "{{username}} has created a new wiki page {{obj_name}} in {{project_name}}",
"MILESTONE_CREATED": "{{username}} has created a new sprint {{obj_name}} in {{project_name}}", "MILESTONE_CREATED": "{{username}} has created a new sprint {{obj_name}} in {{project_name}}",
"EPIC_CREATED": "{{username}} has created a new epic {{obj_name}} in {{project_name}}",
"EPIC_RELATED_USERSTORY_CREATED": "{{username}} has related the userstory {{related_us_name}} to the epic {{epic_name}} in {{project_name}}",
"NEW_PROJECT": "{{username}} ha creat el projecte {{project_name}}", "NEW_PROJECT": "{{username}} ha creat el projecte {{project_name}}",
"MILESTONE_UPDATED": "{{username}} has updated the sprint {{obj_name}}", "MILESTONE_UPDATED": "{{username}} has updated the sprint {{obj_name}}",
"US_UPDATED": "{{username}} has updated the attribute \"{{field_name}}\" of the US {{obj_name}}", "US_UPDATED": "{{username}} has updated the attribute \"{{field_name}}\" of the US {{obj_name}}",
@ -1459,9 +1593,13 @@
"TASK_UPDATED_WITH_US": "{{username}} ha actualitzat l'atribut \"{{field_name}}\" de la tasca {{obj_name}} de la història d'usuari {{us_name}}", "TASK_UPDATED_WITH_US": "{{username}} ha actualitzat l'atribut \"{{field_name}}\" de la tasca {{obj_name}} de la història d'usuari {{us_name}}",
"TASK_UPDATED_WITH_US_NEW_VALUE": "{{username}} ha actualitzat l'atribut \"{{field_name}}\" de la tasca {{obj_name}} de la història d'usuari {{us_name}} amb el valor {{new_value}}", "TASK_UPDATED_WITH_US_NEW_VALUE": "{{username}} ha actualitzat l'atribut \"{{field_name}}\" de la tasca {{obj_name}} de la història d'usuari {{us_name}} amb el valor {{new_value}}",
"WIKI_UPDATED": "{{username}} ha actualitzat la pàgina wiki {{obj_name}}", "WIKI_UPDATED": "{{username}} ha actualitzat la pàgina wiki {{obj_name}}",
"EPIC_UPDATED": "{{username}} has updated the attribute \"{{field_name}}\" of the epic {{obj_name}}",
"EPIC_UPDATED_WITH_NEW_VALUE": "{{username}} has updated the attribute \"{{field_name}}\" of the epic {{obj_name}} to {{new_value}}",
"EPIC_UPDATED_WITH_NEW_COLOR": "{{username}} has updated the \"{{field_name}}\" of the epic {{obj_name}} to <span class=\"new-color\" style=\"background: {{new_value}}\"></span>",
"NEW_COMMENT_US": "{{username}} ha comentat la història d'usuari {{obj_name}}", "NEW_COMMENT_US": "{{username}} ha comentat la història d'usuari {{obj_name}}",
"NEW_COMMENT_ISSUE": "{{username}} ha comentat la incidència {{obj_name}}", "NEW_COMMENT_ISSUE": "{{username}} ha comentat la incidència {{obj_name}}",
"NEW_COMMENT_TASK": "{{username}} ha comentat la tasca {{obj_name}}", "NEW_COMMENT_TASK": "{{username}} ha comentat la tasca {{obj_name}}",
"NEW_COMMENT_EPIC": "{{username}} has commented in the epic {{obj_name}}",
"NEW_MEMBER": "{{project_name}} te un nou membre", "NEW_MEMBER": "{{project_name}} te un nou membre",
"US_ADDED_MILESTONE": "{{username}} ha afegit la història d'usuari {{obj_name}} a {{sprint_name}}", "US_ADDED_MILESTONE": "{{username}} ha afegit la història d'usuari {{obj_name}} a {{sprint_name}}",
"US_MOVED": "{{username}} ha mogut la història d'usuari {{obj_name}}", "US_MOVED": "{{username}} ha mogut la història d'usuari {{obj_name}}",

View File

@ -5,8 +5,8 @@
"OR": "oder", "OR": "oder",
"LOADING": "Wird geladen...", "LOADING": "Wird geladen...",
"LOADING_PROJECT": "Projekt wird geladen...", "LOADING_PROJECT": "Projekt wird geladen...",
"DATE": "DD MMM YYYY", "DATE": "DD. MMM YYYY",
"DATETIME": "DD MMM YYYY HH:mm", "DATETIME": "DD. MMM YYYY HH:mm",
"SAVE": "Speichern", "SAVE": "Speichern",
"CANCEL": "Abbrechen", "CANCEL": "Abbrechen",
"ACCEPT": "Akzeptieren", "ACCEPT": "Akzeptieren",
@ -35,6 +35,8 @@
"ONE_ITEM_LINE": "Ein Eintrag pro Zeile...", "ONE_ITEM_LINE": "Ein Eintrag pro Zeile...",
"NEW_BULK": "Neue Massenerstellung", "NEW_BULK": "Neue Massenerstellung",
"RELATED_TASKS": "Verbundene Aufgaben", "RELATED_TASKS": "Verbundene Aufgaben",
"PREVIOUS": "Previous",
"NEXT": "Weiter",
"LOGOUT": "Ausloggen", "LOGOUT": "Ausloggen",
"EXTERNAL_USER": "ein externer Benutzer", "EXTERNAL_USER": "ein externer Benutzer",
"GENERIC_ERROR": "Eins unserer Helferlein sagt {{error}}.", "GENERIC_ERROR": "Eins unserer Helferlein sagt {{error}}.",
@ -43,8 +45,13 @@
"TEAM_REQUIREMENT": "Team requirement is a requirement that must exist in the project but should have no cost for the client", "TEAM_REQUIREMENT": "Team requirement is a requirement that must exist in the project but should have no cost for the client",
"OWNER": "Projekteigentümer", "OWNER": "Projekteigentümer",
"CAPSLOCK_WARNING": "Achtung! Sie verwenden Großbuchstaben in einem Eingabefeld, dass Groß- und Kleinschreibung berücksichtigt.", "CAPSLOCK_WARNING": "Achtung! Sie verwenden Großbuchstaben in einem Eingabefeld, dass Groß- und Kleinschreibung berücksichtigt.",
"CONFIRM_CLOSE_EDIT_MODE_TITLE": "Are you sure you want to close the edit mode?", "CONFIRM_CLOSE_EDIT_MODE_TITLE": "Sind Sie sicher, dass Sie den Bearbeitungsmodus beenden möchten?",
"CONFIRM_CLOSE_EDIT_MODE_MESSAGE": "Remember that if you close the edit mode without saving all the changes will be lost", "CONFIRM_CLOSE_EDIT_MODE_MESSAGE": "Beachten Sie, dass alle Änderungen verloren gehen, wenn Sie den Bearbeitungsmodus schließen, ohne vorher zu speichern.",
"RELATED_USERSTORIES": "Related user stories",
"CARD": {
"ASSIGN_TO": "Assign To",
"EDIT": "Edit card"
},
"FORM_ERRORS": { "FORM_ERRORS": {
"DEFAULT_MESSAGE": "Dieser Wert scheint ungültig zu sein.", "DEFAULT_MESSAGE": "Dieser Wert scheint ungültig zu sein.",
"TYPE_EMAIL": "Dieser Wert sollte eine gültige E-Mail Adresse enthalten.", "TYPE_EMAIL": "Dieser Wert sollte eine gültige E-Mail Adresse enthalten.",
@ -73,7 +80,7 @@
"PIKADAY": "Ungültiges Datumsformat. Bitte nutze DD MMM YYYY (etwa 23 März 1984)" "PIKADAY": "Ungültiges Datumsformat. Bitte nutze DD MMM YYYY (etwa 23 März 1984)"
}, },
"PICKERDATE": { "PICKERDATE": {
"FORMAT": "DD MMM YYYY", "FORMAT": "DD. MMM YYYY",
"IS_RTL": "falsch", "IS_RTL": "falsch",
"FIRST_DAY_OF_WEEK": "1", "FIRST_DAY_OF_WEEK": "1",
"PREV_MONTH": "Vorheriger Monat", "PREV_MONTH": "Vorheriger Monat",
@ -115,8 +122,9 @@
"USER_STORY": "User-Story", "USER_STORY": "User-Story",
"TASK": "Aufgabe", "TASK": "Aufgabe",
"ISSUE": "Ticket", "ISSUE": "Ticket",
"EPIC": "Epic",
"TAGS": { "TAGS": {
"PLACEHOLDER": "Schlagwort...", "PLACEHOLDER": "Enter tag",
"DELETE": "Schlagwort löschen", "DELETE": "Schlagwort löschen",
"ADD": "Schlagwort hinzufügen" "ADD": "Schlagwort hinzufügen"
}, },
@ -196,9 +204,26 @@
"TITLE": "Filter", "TITLE": "Filter",
"INPUT_PLACEHOLDER": "Betreff oder Verweis", "INPUT_PLACEHOLDER": "Betreff oder Verweis",
"TITLE_ACTION_FILTER_BUTTON": "suche", "TITLE_ACTION_FILTER_BUTTON": "suche",
"BREADCRUMB_TITLE": "zurück zu den Kategorien", "INPUT_SEARCH_PLACEHOLDER": "Thema oder ref",
"BREADCRUMB_FILTERS": "Filter", "TITLE_ACTION_SEARCH": "Suche",
"BREADCRUMB_STATUS": "Status" "ACTION_SAVE_CUSTOM_FILTER": "Als Benutzerfilter speichern",
"PLACEHOLDER_FILTER_NAME": "Benennen Sie den Filter und drücken Sie die Eingabetaste",
"APPLIED_FILTERS_NUM": "filters applied",
"CATEGORIES": {
"TYPE": "Arten",
"STATUS": "Status",
"SEVERITY": "Gewichtung",
"PRIORITIES": "Prioritäten",
"TAGS": "Schlagwörter",
"ASSIGNED_TO": "Zugeordnet zu",
"CREATED_BY": "Erstellt durch",
"CUSTOM_FILTERS": "Benutzerfilter",
"EPIC": "Epic"
},
"CONFIRM_DELETE": {
"TITLE": "Benutzerfilter löschen",
"MESSAGE": "der Benutzerfilter '{{customFilterName}}'"
}
}, },
"WYSIWYG": { "WYSIWYG": {
"H1_BUTTON": "Überschrift 1", "H1_BUTTON": "Überschrift 1",
@ -228,9 +253,18 @@
"PREVIEW_BUTTON": "Vorschau", "PREVIEW_BUTTON": "Vorschau",
"EDIT_BUTTON": "Bearbeiten", "EDIT_BUTTON": "Bearbeiten",
"ATTACH_FILE_HELP": "Dateien per Drag & Drop auf das obere Textfeld anhängen.", "ATTACH_FILE_HELP": "Dateien per Drag & Drop auf das obere Textfeld anhängen.",
"ATTACH_FILE_HELP_SAVE_FIRST": "Save first before if you want to attach files by dragging & dropping on the textarea above.",
"MARKDOWN_HELP": "Markdown syntax Hilfe" "MARKDOWN_HELP": "Markdown syntax Hilfe"
}, },
"PERMISIONS_CATEGORIES": { "PERMISIONS_CATEGORIES": {
"EPICS": {
"NAME": "Epics",
"VIEW_EPICS": "View epics",
"ADD_EPICS": "Add epics",
"MODIFY_EPICS": "Modify epics",
"COMMENT_EPICS": "Comment epics",
"DELETE_EPICS": "Delete epics"
},
"SPRINTS": { "SPRINTS": {
"NAME": "Sprints", "NAME": "Sprints",
"VIEW_SPRINTS": "Sprints ansehen", "VIEW_SPRINTS": "Sprints ansehen",
@ -243,6 +277,7 @@
"VIEW_USER_STORIES": "User-Stories ansehen", "VIEW_USER_STORIES": "User-Stories ansehen",
"ADD_USER_STORIES": "User-Stories hinzufügen", "ADD_USER_STORIES": "User-Stories hinzufügen",
"MODIFY_USER_STORIES": "User-Stories modifizieren", "MODIFY_USER_STORIES": "User-Stories modifizieren",
"COMMENT_USER_STORIES": "Comment user stories",
"DELETE_USER_STORIES": "User-Stories löschen" "DELETE_USER_STORIES": "User-Stories löschen"
}, },
"TASKS": { "TASKS": {
@ -250,6 +285,7 @@
"VIEW_TASKS": "Aufgaben ansehen", "VIEW_TASKS": "Aufgaben ansehen",
"ADD_TASKS": "Aufgaben hinzufügen", "ADD_TASKS": "Aufgaben hinzufügen",
"MODIFY_TASKS": "Aufgaben ändern", "MODIFY_TASKS": "Aufgaben ändern",
"COMMENT_TASKS": "Comment tasks",
"DELETE_TASKS": "Aufgaben löschen" "DELETE_TASKS": "Aufgaben löschen"
}, },
"ISSUES": { "ISSUES": {
@ -257,6 +293,7 @@
"VIEW_ISSUES": "Tickets ansehen", "VIEW_ISSUES": "Tickets ansehen",
"ADD_ISSUES": "Tickets hinzufügen", "ADD_ISSUES": "Tickets hinzufügen",
"MODIFY_ISSUES": "Tickets ändern", "MODIFY_ISSUES": "Tickets ändern",
"COMMENT_ISSUES": "Comment issues",
"DELETE_ISSUES": "Tickets löschen" "DELETE_ISSUES": "Tickets löschen"
}, },
"WIKI": { "WIKI": {
@ -289,7 +326,7 @@
"HEADER": "Ich bin bereits bei Taiga angemeldet", "HEADER": "Ich bin bereits bei Taiga angemeldet",
"PLACEHOLDER_AUTH_NAME": "Benutzername oder E-Mail-Adresse", "PLACEHOLDER_AUTH_NAME": "Benutzername oder E-Mail-Adresse",
"LINK_FORGOT_PASSWORD": "Haben Sie es vergessen?", "LINK_FORGOT_PASSWORD": "Haben Sie es vergessen?",
"TITLE_LINK_FORGOT_PASSWORD": "Did you forget your password?", "TITLE_LINK_FORGOT_PASSWORD": "Haben Sie Ihr Passwort vergessen?",
"ACTION_ENTER": "Eingabe", "ACTION_ENTER": "Eingabe",
"ACTION_SIGN_IN": "Login", "ACTION_SIGN_IN": "Login",
"PLACEHOLDER_AUTH_PASSWORD": "Passwort" "PLACEHOLDER_AUTH_PASSWORD": "Passwort"
@ -366,6 +403,41 @@
"WATCHING_SECTION": "Beobachtet", "WATCHING_SECTION": "Beobachtet",
"DASHBOARD": "ProjeKte Dashboard" "DASHBOARD": "ProjeKte Dashboard"
}, },
"EPICS": {
"TITLE": "EPICS",
"SECTION_NAME": "Epics",
"EPIC": "EPIC",
"PAGE_TITLE": "Epics - {{projectName}}",
"PAGE_DESCRIPTION": "The epics list of the project {{projectName}}: {{projectDescription}}",
"DASHBOARD": {
"ADD": "+ EPIC HINZUFÜGEN",
"UNASSIGNED": "Nicht zugeordnet"
},
"EMPTY": {
"TITLE": "It looks like there aren't any epics yet",
"EXPLANATION": "Epics are items at a higher level that encompass user stories.<br />Epics are at the top of the hierarchy and can be used to group user stories together.",
"HELP": "Erfahren Sie mehr über Epics"
},
"TABLE": {
"VOTES": "Stimmen",
"NAME": "Name",
"PROJECT": "Projekt",
"SPRINT": "Sprint",
"ASSIGNED_TO": "Zugewiesen",
"STATUS": "Status",
"PROGRESS": "Fortschritt",
"VIEW_OPTIONS": "View options"
},
"CREATE": {
"TITLE": "Neues Epic",
"PLACEHOLDER_DESCRIPTION": "Please add descriptive text to help others better understand this epic",
"TEAM_REQUIREMENT": "Team-Anforderung",
"CLIENT_REQUIREMENT": "Kunden-Anforderung",
"BLOCKED": "Blockiert",
"BLOCKED_NOTE_PLACEHOLDER": "Warum ist dieses Epic geblockt?",
"CREATE_EPIC": "Epic erzeugen"
}
},
"PROJECTS": { "PROJECTS": {
"PAGE_TITLE": "Meine Projekte - Taiga", "PAGE_TITLE": "Meine Projekte - Taiga",
"PAGE_DESCRIPTION": "Eine Liste mit all Deinen Projekten. Du kannst sie ordnen oder ein Neues anlegen.", "PAGE_DESCRIPTION": "Eine Liste mit all Deinen Projekten. Du kannst sie ordnen oder ein Neues anlegen.",
@ -385,7 +457,7 @@
"HIDE_DEPRECATED": "- verworfene Anhänge verbergen", "HIDE_DEPRECATED": "- verworfene Anhänge verbergen",
"COUNT_DEPRECATED": "({{ counter }} verworfen)", "COUNT_DEPRECATED": "({{ counter }} verworfen)",
"MAX_UPLOAD_SIZE": "Die maximale Dateigröße beträgt {{maxFileSize}}", "MAX_UPLOAD_SIZE": "Die maximale Dateigröße beträgt {{maxFileSize}}",
"DATE": "DD MMM YYYY [um] hh:mm", "DATE": "DD. MMM YYYY [um] hh:mm",
"ERROR_UPLOAD_ATTACHMENT": "Das Hochladen war uns nicht möglich '{{fileName}}'. {{errorMessage}}", "ERROR_UPLOAD_ATTACHMENT": "Das Hochladen war uns nicht möglich '{{fileName}}'. {{errorMessage}}",
"TITLE_LIGHTBOX_DELETE_ATTACHMENT": "Anhang löschen...", "TITLE_LIGHTBOX_DELETE_ATTACHMENT": "Anhang löschen...",
"MSG_LIGHTBOX_DELETE_ATTACHMENT": "der Anhang '{{fileName}}'", "MSG_LIGHTBOX_DELETE_ATTACHMENT": "der Anhang '{{fileName}}'",
@ -402,7 +474,8 @@
"ADMIN": { "ADMIN": {
"COMMON": { "COMMON": {
"TITLE_ACTION_EDIT_VALUE": "Wert bearbeiten", "TITLE_ACTION_EDIT_VALUE": "Wert bearbeiten",
"TITLE_ACTION_DELETE_VALUE": "Wert löschen" "TITLE_ACTION_DELETE_VALUE": "Wert löschen",
"TITLE_ACTION_DELETE_TAG": "Schlagwort löschen"
}, },
"HELP": "Wenn Sie Hilfe benötigen, besuchen Sie unsere Support-Seite!", "HELP": "Wenn Sie Hilfe benötigen, besuchen Sie unsere Support-Seite!",
"PROJECT_DEFAULT_VALUES": { "PROJECT_DEFAULT_VALUES": {
@ -435,6 +508,8 @@
"TITLE": "Module", "TITLE": "Module",
"ENABLE": "Aktivieren", "ENABLE": "Aktivieren",
"DISABLE": "Deaktivieren", "DISABLE": "Deaktivieren",
"EPICS": "Epics",
"EPICS_DESCRIPTION": "Visualisieren und verwalten Sie den strategischsten Teil Ihres Projektes",
"BACKLOG": "Auftragsliste", "BACKLOG": "Auftragsliste",
"BACKLOG_DESCRIPTION": "Verwalten Sie Ihre User-Stories, um einen organisierten Überblick der anstehenden und priorisierten Aufgaben zu erhalten.", "BACKLOG_DESCRIPTION": "Verwalten Sie Ihre User-Stories, um einen organisierten Überblick der anstehenden und priorisierten Aufgaben zu erhalten.",
"NUMBER_SPRINTS": "Erwartete Anzahl an Sprints", "NUMBER_SPRINTS": "Erwartete Anzahl an Sprints",
@ -452,9 +527,9 @@
"SELECT_VIDEOCONFERENCE": "Wählen Sie ein Videokonferenzsystem", "SELECT_VIDEOCONFERENCE": "Wählen Sie ein Videokonferenzsystem",
"SALT_CHAT_ROOM": "Fügen Sie ein Präfix für den Chatraum-Namen hinzu", "SALT_CHAT_ROOM": "Fügen Sie ein Präfix für den Chatraum-Namen hinzu",
"JITSI_CHAT_ROOM": "Jitsi", "JITSI_CHAT_ROOM": "Jitsi",
"APPEARIN_CHAT_ROOM": "Erscheint in", "APPEARIN_CHAT_ROOM": "Appear.in",
"TALKY_CHAT_ROOM": "Gesprächig", "TALKY_CHAT_ROOM": "Talky.io",
"CUSTOM_CHAT_ROOM": "Kunde", "CUSTOM_CHAT_ROOM": "Benutzerdefiniert",
"URL_CHAT_ROOM": "URL Ihres Chatrooms" "URL_CHAT_ROOM": "URL Ihres Chatrooms"
}, },
"PROJECT_PROFILE": { "PROJECT_PROFILE": {
@ -497,6 +572,7 @@
"REGENERATE_SUBTITLE": "Sie sind im Begriff, die CSV data access URL zu ändern. Die vorherige URL wird deaktiviert. Sind Sie sicher?" "REGENERATE_SUBTITLE": "Sie sind im Begriff, die CSV data access URL zu ändern. Die vorherige URL wird deaktiviert. Sind Sie sicher?"
}, },
"CSV": { "CSV": {
"SECTION_TITLE_EPIC": "epics reports",
"SECTION_TITLE_US": "User-Stories Berichte", "SECTION_TITLE_US": "User-Stories Berichte",
"SECTION_TITLE_TASK": "Aufgabenberichte", "SECTION_TITLE_TASK": "Aufgabenberichte",
"SECTION_TITLE_ISSUE": "Ticket Berichte", "SECTION_TITLE_ISSUE": "Ticket Berichte",
@ -509,6 +585,8 @@
"CUSTOM_FIELDS": { "CUSTOM_FIELDS": {
"TITLE": "Benutzerfelder", "TITLE": "Benutzerfelder",
"SUBTITLE": "Spezifizieren Sie die Benutzerfelder für Ihre User-Stories, Aufgaben und Tickets.", "SUBTITLE": "Spezifizieren Sie die Benutzerfelder für Ihre User-Stories, Aufgaben und Tickets.",
"EPIC_DESCRIPTION": "Epics custom fields",
"EPIC_ADD": "Add a custom field in epics",
"US_DESCRIPTION": "Benutzerdefinierte Felder der User-Story", "US_DESCRIPTION": "Benutzerdefinierte Felder der User-Story",
"US_ADD": "Benutzerdefiniertes Feld bei User-Stories hinzufügen", "US_ADD": "Benutzerdefiniertes Feld bei User-Stories hinzufügen",
"TASK_DESCRIPTION": "Aufgaben benutzerdefinierte Felder", "TASK_DESCRIPTION": "Aufgaben benutzerdefinierte Felder",
@ -546,7 +624,8 @@
"PROJECT_VALUES_STATUS": { "PROJECT_VALUES_STATUS": {
"TITLE": "Status", "TITLE": "Status",
"SUBTITLE": "Spezifizieren Sie die Status, die Ihre User-Stories, Aufgaben und Tickets durchlaufen werden.", "SUBTITLE": "Spezifizieren Sie die Status, die Ihre User-Stories, Aufgaben und Tickets durchlaufen werden.",
"US_TITLE": "User-Story Status", "EPIC_TITLE": "Epic Statuses",
"US_TITLE": "User Story Statuses",
"TASK_TITLE": "Aufgaben-Status", "TASK_TITLE": "Aufgaben-Status",
"ISSUE_TITLE": "Ticket-Status" "ISSUE_TITLE": "Ticket-Status"
}, },
@ -556,6 +635,17 @@
"ISSUE_TITLE": "Ticketarten", "ISSUE_TITLE": "Ticketarten",
"ACTION_ADD": "Neu hinzufügen {{objName}}" "ACTION_ADD": "Neu hinzufügen {{objName}}"
}, },
"PROJECT_VALUES_TAGS": {
"TITLE": "Schlagwörter",
"SUBTITLE": "View and edit the color of your tags",
"EMPTY": "Currently there are no tags",
"EMPTY_SEARCH": "Es sieht so aus, als konnte zu Ihren Suchkriterien nichts passendes gefunden werden.",
"ACTION_ADD": "Schlagwort hinzufügen",
"NEW_TAG": "New tag",
"MIXING_HELP_TEXT": "Select the tags that you want to merge",
"MIXING_MERGE": "Merge Tags",
"SELECTED": "Selected"
},
"ROLES": { "ROLES": {
"PAGE_TITLE": "Rollen - {{projectName}}", "PAGE_TITLE": "Rollen - {{projectName}}",
"WARNING_NO_ROLE": "Beachten Sie, keine Rolle in Ihrem Projekt wird in der Lage sein, die Punktevergabe für User-Stories einzuschätzen.", "WARNING_NO_ROLE": "Beachten Sie, keine Rolle in Ihrem Projekt wird in der Lage sein, die Punktevergabe für User-Stories einzuschätzen.",
@ -588,6 +678,10 @@
"SECTION_NAME": "Github", "SECTION_NAME": "Github",
"PAGE_TITLE": "Github - {{projectName}}" "PAGE_TITLE": "Github - {{projectName}}"
}, },
"GOGS": {
"SECTION_NAME": "Gogs",
"PAGE_TITLE": "Gogs - {{projectName}}"
},
"WEBHOOKS": { "WEBHOOKS": {
"PAGE_TITLE": "Webhooks - {{projectName}}", "PAGE_TITLE": "Webhooks - {{projectName}}",
"SECTION_NAME": "Webhooks", "SECTION_NAME": "Webhooks",
@ -607,7 +701,7 @@
"HEADERS": "Überschriften", "HEADERS": "Überschriften",
"PAYLOAD": "Ladung", "PAYLOAD": "Ladung",
"RESPONSE": "Rückmeldung", "RESPONSE": "Rückmeldung",
"DATE": "DD MMM YYYY [um] hh:mm:ss", "DATE": "DD. MMM YYYY [um] hh:mm:ss",
"ACTION_HIDE_HISTORY": "(Chronik verbergen)", "ACTION_HIDE_HISTORY": "(Chronik verbergen)",
"ACTION_HIDE_HISTORY_TITLE": "Chronik Details verbergen", "ACTION_HIDE_HISTORY_TITLE": "Chronik Details verbergen",
"ACTION_SHOW_HISTORY": "(Chronik anzeigen)", "ACTION_SHOW_HISTORY": "(Chronik anzeigen)",
@ -643,13 +737,14 @@
"DEFAULT_DELETE_MESSAGE": "die Einladung an {{email}}" "DEFAULT_DELETE_MESSAGE": "die Einladung an {{email}}"
}, },
"DEFAULT_VALUES": { "DEFAULT_VALUES": {
"LABEL_EPIC_STATUS": "Default value for epic status selector",
"LABEL_US_STATUS": "Default value for user story status selector",
"LABEL_POINTS": "Vorgegebener Wert für Punkteauswahl", "LABEL_POINTS": "Vorgegebener Wert für Punkteauswahl",
"LABEL_US": "Vorgegebener Wert für User-Story-Status Auswahl",
"LABEL_TASK_STATUS": "Vorgegebene Auswahl für den Aufgaben-Status", "LABEL_TASK_STATUS": "Vorgegebene Auswahl für den Aufgaben-Status",
"LABEL_PRIORITY": "Vorgegebener Wert für Prioritätsauswahl",
"LABEL_SEVERITY": "Vorgegebener Wert für Gewichtungsauswahl",
"LABEL_ISSUE_TYPE": "Vorgegebener Wert für Ticketartauswahl", "LABEL_ISSUE_TYPE": "Vorgegebener Wert für Ticketartauswahl",
"LABEL_ISSUE_STATUS": "Vorgegebene Auswahl für den Ticket-Status" "LABEL_ISSUE_STATUS": "Vorgegebene Auswahl für den Ticket-Status",
"LABEL_PRIORITY": "Vorgegebener Wert für Prioritätsauswahl",
"LABEL_SEVERITY": "Vorgegebener Wert für Gewichtungsauswahl"
}, },
"STATUS": { "STATUS": {
"PLACEHOLDER_WRITE_STATUS_NAME": "Benennen Sie den neuen Status" "PLACEHOLDER_WRITE_STATUS_NAME": "Benennen Sie den neuen Status"
@ -681,7 +776,8 @@
"PRIORITIES": "Prioritäten", "PRIORITIES": "Prioritäten",
"SEVERITIES": "Schweregrade", "SEVERITIES": "Schweregrade",
"TYPES": "Typen", "TYPES": "Typen",
"CUSTOM_FIELDS": "Benutzerdefinierte Felder" "CUSTOM_FIELDS": "Benutzerdefinierte Felder",
"TAGS": "Schlagwörter"
}, },
"SUBMENU_PROJECT_PROFILE": { "SUBMENU_PROJECT_PROFILE": {
"TITLE": "Projektprofil" "TITLE": "Projektprofil"
@ -751,6 +847,8 @@
"FILTER_TYPE_ALL_TITLE": "Alle anzeigen", "FILTER_TYPE_ALL_TITLE": "Alle anzeigen",
"FILTER_TYPE_PROJECTS": "Projekte", "FILTER_TYPE_PROJECTS": "Projekte",
"FILTER_TYPE_PROJECT_TITLES": "Nur Projekte anzeigen", "FILTER_TYPE_PROJECT_TITLES": "Nur Projekte anzeigen",
"FILTER_TYPE_EPICS": "Epics",
"FILTER_TYPE_EPIC_TITLES": "Show only epics",
"FILTER_TYPE_USER_STORIES": "Stories", "FILTER_TYPE_USER_STORIES": "Stories",
"FILTER_TYPE_USER_STORIES_TITLES": "Nur User-Stories anzeigen", "FILTER_TYPE_USER_STORIES_TITLES": "Nur User-Stories anzeigen",
"FILTER_TYPE_TASKS": "Aufgaben", "FILTER_TYPE_TASKS": "Aufgaben",
@ -950,8 +1048,8 @@
"CREATE_MEMBER": { "CREATE_MEMBER": {
"PLACEHOLDER_INVITATION_TEXT": "(Optional) Fügen Sie einen persönlichen Text zur Einladung hinzu. Erzählen Sie Ihren neuen Mitgliedern etwas Schönes. ;-)", "PLACEHOLDER_INVITATION_TEXT": "(Optional) Fügen Sie einen persönlichen Text zur Einladung hinzu. Erzählen Sie Ihren neuen Mitgliedern etwas Schönes. ;-)",
"PLACEHOLDER_TYPE_EMAIL": "Geben Sie eine E-Mail ein", "PLACEHOLDER_TYPE_EMAIL": "Geben Sie eine E-Mail ein",
"LIMIT_USERS_WARNING_MESSAGE_FOR_OWNER": "Leider kann dieses Projekt nicht mehr als <strong>{{maxMembers}}</strong> Mitglieder haben. Wenn Sie die derzeitige Grenze erhöhen möchten, kontaktieren Sie den Administrator.", "LIMIT_USERS_WARNING_MESSAGE_FOR_OWNER": "You are about to reach the maximum number of members allowed for this project, <strong>{{maxMembers}}</strong> members. If you would like to increase the current limit, please contact the administrator.",
"LIMIT_USERS_WARNING_MESSAGE": "Leider kann dieses Projekt nicht mehr als <strong>{{maxMembers}}</strong> Mitglieder haben." "LIMIT_USERS_WARNING_MESSAGE": "You are about to reach the maximum number of members allowed for this project, <strong>{{maxMembers}}</strong> members."
}, },
"LEAVE_PROJECT_WARNING": { "LEAVE_PROJECT_WARNING": {
"TITLE": "Das Projekt kann nicht ohne einen Projektleiter existieren.", "TITLE": "Das Projekt kann nicht ohne einen Projektleiter existieren.",
@ -970,10 +1068,30 @@
"BUTTON": "Fragen Sie dieses Projektmitglied, um Projektleiter zu werden" "BUTTON": "Fragen Sie dieses Projektmitglied, um Projektleiter zu werden"
} }
}, },
"EPIC": {
"PAGE_TITLE": "{{epicSubject}} - Epic {{epicRef}} - {{projectName}}",
"PAGE_DESCRIPTION": "Status: {{epicStatus }}. Description: {{epicDescription}}",
"SECTION_NAME": "Epic",
"TITLE_LIGHTBOX_UNLINK_RELATED_USERSTORY": "Unlink related userstory",
"MSG_LIGHTBOX_UNLINK_RELATED_USERSTORY": "It will delete the link to the related userstory '{{subject}}'",
"ERROR_UNLINK_RELATED_USERSTORY": "We have not been able to unlink: {{errorMessage}}",
"CREATE_RELATED_USERSTORIES": "Create a relationship with",
"NEW_USERSTORY": "Neue User-Story",
"EXISTING_USERSTORY": "Existing user story",
"CHOOSE_PROJECT_FOR_CREATION": "What's the project?",
"SUBJECT": "Thema",
"SUBJECT_BULK_MODE": "Subject (bulk insert)",
"CHOOSE_PROJECT_FROM": "What's the project?",
"CHOOSE_USERSTORY": "What's the user story?",
"NO_USERSTORIES": "This project has no User Stories yet. Please select another project.",
"FILTER_USERSTORIES": "Filter user stories",
"LIGHTBOX_TITLE_BLOKING_EPIC": "Blocking epic",
"ACTION_DELETE": "Delete epic"
},
"US": { "US": {
"PAGE_TITLE": "{{userStorySubject}} - User-Story {{userStoryRef}} - {{projectName}}", "PAGE_TITLE": "{{userStorySubject}} - User-Story {{userStoryRef}} - {{projectName}}",
"PAGE_DESCRIPTION": "Status: {{userStoryStatus }}. Abgeschlossen {{userStoryProgressPercentage}}% ({{userStoryClosedTasks}} von {{userStoryTotalTasks}} Aufgaben geschlossen). Punkte: {{userStoryPoints}}. Beschreibung: {{userStoryDescription}}", "PAGE_DESCRIPTION": "Status: {{userStoryStatus }}. Abgeschlossen {{userStoryProgressPercentage}}% ({{userStoryClosedTasks}} von {{userStoryTotalTasks}} Aufgaben geschlossen). Punkte: {{userStoryPoints}}. Beschreibung: {{userStoryDescription}}",
"SECTION_NAME": "User-Story Details", "SECTION_NAME": "User-Story",
"LINK_TASKBOARD": "Taskboard", "LINK_TASKBOARD": "Taskboard",
"TITLE_LINK_TASKBOARD": "Zu Taskboard wechseln", "TITLE_LINK_TASKBOARD": "Zu Taskboard wechseln",
"TOTAL_POINTS": "Gesamtpunkte", "TOTAL_POINTS": "Gesamtpunkte",
@ -984,14 +1102,23 @@
"EXTERNAL_REFERENCE": "Dies User-Story wurde angelegt von", "EXTERNAL_REFERENCE": "Dies User-Story wurde angelegt von",
"GO_TO_EXTERNAL_REFERENCE": "Zur Quelle wechseln", "GO_TO_EXTERNAL_REFERENCE": "Zur Quelle wechseln",
"BLOCKED": "Diese User-Story wird blockiert", "BLOCKED": "Diese User-Story wird blockiert",
"PREVIOUS": "Vorherige User-Story",
"NEXT": "nächste User-Story",
"TITLE_DELETE_ACTION": "User-Story löschen", "TITLE_DELETE_ACTION": "User-Story löschen",
"LIGHTBOX_TITLE_BLOKING_US": "Blockiert uns", "LIGHTBOX_TITLE_BLOKING_US": "Blockiert uns",
"TASK_COMPLETED": "{{totalClosedTasks}}/{{totalTasks}} Aufgaben fertiggestellt", "TASK_COMPLETED": "{{totalClosedTasks}}/{{totalTasks}} Aufgaben fertiggestellt",
"ASSIGN": "Zugeordnete User-Story", "ASSIGN": "Zugeordnete User-Story",
"NOT_ESTIMATED": "Nicht eingeschätzt", "NOT_ESTIMATED": "Nicht eingeschätzt",
"TOTAL_US_POINTS": "User-Story-Punkte insgesamt", "TOTAL_US_POINTS": "User-Story-Punkte insgesamt",
"TRIBE": {
"PUBLISH": "Als Gig in Taiga Tribe veröffentlichen",
"PUBLISH_INFO": "Weitere Infos",
"PUBLISH_TITLE": "More info on publishing in Taiga Tribe",
"PUBLISHED_AS_GIG": "Story veröffentlicht als Gig in Taiga Tribe",
"EDIT_LINK": "Link bearbeiten",
"CLOSE": "Schließen",
"SYNCHRONIZE_LINK": "mit Taiga Tribe synchronisieren",
"PUBLISH_MORE_INFO_TITLE": "Brauchen Sie jemanden für diese Aufgabe?",
"PUBLISH_MORE_INFO_TEXT": "<p>If you need help with a particular piece of work you can easily create gigs on<a href='taigatribe.com' title='Taiga Tribe'> Taiga Tribe </a> and receive help from all over the world. You will be able to control and manage the gig enjoying a great community eager to contribute.</p><p><a href='taigatribe.com' title='Taiga Tribe'> TaigaTribe </a> was born as a Taiga sibling. Both platforms can live separately but we believe that there is much power in using them combined so we are making sure the integration works like a charm.</p>"
},
"FIELDS": { "FIELDS": {
"TEAM_REQUIREMENT": "Team Anforderung", "TEAM_REQUIREMENT": "Team Anforderung",
"CLIENT_REQUIREMENT": "Kundenanforderung", "CLIENT_REQUIREMENT": "Kundenanforderung",
@ -999,28 +1126,47 @@
} }
}, },
"COMMENTS": { "COMMENTS": {
"DELETED_INFO": "Kommentar gelöscht von {{user}} am {{date}}", "DELETED_INFO": "Kommentar gelöscht von {{user}}",
"TITLE": "Kommentare", "TITLE": "Kommentare",
"COMMENTS_COUNT": "{{comments}} Kommentare",
"ORDER": "Reihenfolge",
"OLDER_FIRST": "Ältere zuerst",
"RECENT_FIRST": "Letzte zuerst",
"COMMENT": "Kommentieren", "COMMENT": "Kommentieren",
"EDIT_COMMENT": "Kommentar bearbeiten",
"EDITED_COMMENT": "Bearbeitet:",
"SHOW_HISTORY": "View historic",
"TYPE_NEW_COMMENT": "Geben Sie hier einen neuen Kommentar ein", "TYPE_NEW_COMMENT": "Geben Sie hier einen neuen Kommentar ein",
"SHOW_DELETED": "Gelöschten Kommentar anzeigen", "SHOW_DELETED": "Gelöschten Kommentar anzeigen",
"HIDE_DELETED": "Gelöschten Kommentar ausblenden", "HIDE_DELETED": "Gelöschten Kommentar ausblenden",
"DELETE": "Kommentar löschen", "DELETE": "Kommentar löschen",
"RESTORE": "Kommentar wiederherstellen" "RESTORE": "Kommentar wiederherstellen",
"HISTORY": {
"TITLE": "Aktivität"
}
}, },
"ACTIVITY": { "ACTIVITY": {
"SHOW_ACTIVITY": "Aktivitäten zeigen", "SHOW_ACTIVITY": "Aktivitäten zeigen",
"DATETIME": "DD MMM YYYY HH:mm", "DATETIME": "DD. MMM YYYY HH:mm",
"SHOW_MORE": "+ Vorherige Einträge zeigen ({{showMore}} vorhanden)", "SHOW_MORE": "+ Vorherige Einträge zeigen ({{showMore}} vorhanden)",
"TITLE": "Aktivität", "TITLE": "Aktivität",
"ACTIVITIES_COUNT": "{{activities}} Aktivitäten",
"REMOVED": "entfernt", "REMOVED": "entfernt",
"ADDED": "hinzugefügt", "ADDED": "hinzugefügt",
"US_POINTS": "User-Story Punkte ({{name}})", "TAGS_ADDED": "Tags hinzugefügt:",
"NEW_ATTACHMENT": "Neuer Anhang", "TAGS_REMOVED": "Tags entfernt:",
"DELETED_ATTACHMENT": "Gelöschter Anhang", "US_POINTS": "{{role}} points",
"UPDATED_ATTACHMENT": "aktualisierter Anhang {{filename}}", "NEW_ATTACHMENT": "neuer Anhang:",
"DELETED_CUSTOM_ATTRIBUTE": "gelöschtes Kundenattribut", "DELETED_ATTACHMENT": "gelöschter Anhang:",
"UPDATED_ATTACHMENT": "updated attachment ({{filename}}):",
"CREATED_CUSTOM_ATTRIBUTE": "created custom attribute",
"UPDATED_CUSTOM_ATTRIBUTE": "updated custom attribute",
"SIZE_CHANGE": "Machte {size, plural, one{eine Änderung} other{# Änderungen}}", "SIZE_CHANGE": "Machte {size, plural, one{eine Änderung} other{# Änderungen}}",
"BECAME_DEPRECATED": "ist veraltet",
"BECAME_UNDEPRECATED": "became undeprecated",
"TEAM_REQUIREMENT": "Team Anforderung",
"CLIENT_REQUIREMENT": "Kundenanforderung",
"BLOCKED": "Blockiert",
"VALUES": { "VALUES": {
"YES": "ja", "YES": "ja",
"NO": "nein", "NO": "nein",
@ -1052,12 +1198,14 @@
"TAGS": "Schlagwörter", "TAGS": "Schlagwörter",
"ATTACHMENTS": "Anhänge", "ATTACHMENTS": "Anhänge",
"IS_DEPRECATED": "ist veraltet", "IS_DEPRECATED": "ist veraltet",
"IS_NOT_DEPRECATED": "ist nicht verworfen",
"ORDER": "Befehl", "ORDER": "Befehl",
"BACKLOG_ORDER": "Backlog Befehl", "BACKLOG_ORDER": "Backlog Befehl",
"SPRINT_ORDER": "Sprint Befehl", "SPRINT_ORDER": "Sprint Befehl",
"KANBAN_ORDER": "Kanban Befehl", "KANBAN_ORDER": "Kanban Befehl",
"TASKBOARD_ORDER": "Taskboard Befehl", "TASKBOARD_ORDER": "Taskboard Befehl",
"US_ORDER": "User-Story Befehl" "US_ORDER": "User-Story Befehl",
"COLOR": "Farbe"
} }
}, },
"BACKLOG": { "BACKLOG": {
@ -1109,7 +1257,8 @@
"CLOSED_TASKS": "geschlossene<br />Aufgaben", "CLOSED_TASKS": "geschlossene<br />Aufgaben",
"IOCAINE_DOSES": "Iocaine<br />Dosen", "IOCAINE_DOSES": "Iocaine<br />Dosen",
"SHOW_STATISTICS_TITLE": "Statistik anzeigen", "SHOW_STATISTICS_TITLE": "Statistik anzeigen",
"TOGGLE_BAKLOG_GRAPH": "Zeige/Verstecke Burndowngraph" "TOGGLE_BAKLOG_GRAPH": "Zeige/Verstecke Burndowngraph",
"POINTS_PER_ROLE": "Points pro Rolle"
}, },
"SUMMARY": { "SUMMARY": {
"PROJECT_POINTS": "Projekt<br />Punkte", "PROJECT_POINTS": "Projekt<br />Punkte",
@ -1122,13 +1271,11 @@
"TITLE": "Filter", "TITLE": "Filter",
"REMOVE": "Filter entfernen", "REMOVE": "Filter entfernen",
"HIDE": "Filter verbergen", "HIDE": "Filter verbergen",
"SHOW": "Filter anzeigen", "SHOW": "Filter anzeigen"
"FILTER_CATEGORY_STATUS": "Status",
"FILTER_CATEGORY_TAGS": "Schlagwörter"
}, },
"SPRINTS": { "SPRINTS": {
"TITLE": "SPRINTS", "TITLE": "SPRINTS",
"DATE": "DD MMM YYYY", "DATE": "DD. MMM YYYY",
"LINK_TASKBOARD": "Sprint Taskboard", "LINK_TASKBOARD": "Sprint Taskboard",
"TITLE_LINK_TASKBOARD": "Gehe zu Taskboard von \"{{name}}\"", "TITLE_LINK_TASKBOARD": "Gehe zu Taskboard von \"{{name}}\"",
"NUMBER_SPRINTS": "<br/>Sprints", "NUMBER_SPRINTS": "<br/>Sprints",
@ -1173,13 +1320,13 @@
"YAXIS_LABEL": "Punkte", "YAXIS_LABEL": "Punkte",
"OPTIMAL": "Optimale unerledigte Punkte für Tag {{formattedDate}} sollten sein {{roundedValue}}", "OPTIMAL": "Optimale unerledigte Punkte für Tag {{formattedDate}} sollten sein {{roundedValue}}",
"REAL": "Tatsächliche Anzahl unerledigter Punkte für Tag {{formattedDate}} ist {{roundedValue}}", "REAL": "Tatsächliche Anzahl unerledigter Punkte für Tag {{formattedDate}} ist {{roundedValue}}",
"DATE": "DD MMMM YYYY" "DATE": "DD. MMMM YYYY"
} }
}, },
"TASK": { "TASK": {
"PAGE_TITLE": "{{taskSubject}} - Aufgabe {{taskRef}} - {{projectName}}", "PAGE_TITLE": "{{taskSubject}} - Aufgabe {{taskRef}} - {{projectName}}",
"PAGE_DESCRIPTION": "Status: {{taskStatus }}. Beschreibung: {{taskDescription}}", "PAGE_DESCRIPTION": "Status: {{taskStatus }}. Beschreibung: {{taskDescription}}",
"SECTION_NAME": "Aufgabendetails", "SECTION_NAME": "Aufgabe",
"LINK_TASKBOARD": "Taskboard", "LINK_TASKBOARD": "Taskboard",
"TITLE_LINK_TASKBOARD": "Zu Taskboard wechseln", "TITLE_LINK_TASKBOARD": "Zu Taskboard wechseln",
"PLACEHOLDER_SUBJECT": "Betreff...", "PLACEHOLDER_SUBJECT": "Betreff...",
@ -1189,8 +1336,6 @@
"ORIGIN_US": "Diese Aufgabe wurde erstellt durch", "ORIGIN_US": "Diese Aufgabe wurde erstellt durch",
"TITLE_LINK_GO_ORIGIN": "Zu User-Story wechseln", "TITLE_LINK_GO_ORIGIN": "Zu User-Story wechseln",
"BLOCKED": "Diese Aufgabe wird blockiert", "BLOCKED": "Diese Aufgabe wird blockiert",
"PREVIOUS": "vorherige Aufgabe",
"NEXT": "nächste Aufgabe",
"TITLE_DELETE_ACTION": "Aufgabe löschen", "TITLE_DELETE_ACTION": "Aufgabe löschen",
"LIGHTBOX_TITLE_BLOKING_TASK": "Blockierende Aufgabe", "LIGHTBOX_TITLE_BLOKING_TASK": "Blockierende Aufgabe",
"FIELDS": { "FIELDS": {
@ -1228,16 +1373,13 @@
"PAGE_TITLE": "Tickets - {{projectName}}", "PAGE_TITLE": "Tickets - {{projectName}}",
"PAGE_DESCRIPTION": "Das Ticket-Listen Panel des Projekts {{projectName}}: {{projectDescription}}", "PAGE_DESCRIPTION": "Das Ticket-Listen Panel des Projekts {{projectName}}: {{projectDescription}}",
"LIST_SECTION_NAME": "Tickets", "LIST_SECTION_NAME": "Tickets",
"SECTION_NAME": "Ticket Details", "SECTION_NAME": "Ticket",
"ACTION_NEW_ISSUE": "+ NEUES TICKET", "ACTION_NEW_ISSUE": "+ NEUES TICKET",
"ACTION_PROMOTE_TO_US": "Zur User-Story aufwerten", "ACTION_PROMOTE_TO_US": "Zur User-Story aufwerten",
"PLACEHOLDER_FILTER_NAME": "Benennen Sie den Filter und drücken Sie die Eingabetaste",
"PROMOTED": "Dieses Ticket wurde aufgewertet zu User-Story:", "PROMOTED": "Dieses Ticket wurde aufgewertet zu User-Story:",
"EXTERNAL_REFERENCE": "Dieses Ticket wurde erstellt durch", "EXTERNAL_REFERENCE": "Dieses Ticket wurde erstellt durch",
"GO_TO_EXTERNAL_REFERENCE": "Zur Quelle wechseln", "GO_TO_EXTERNAL_REFERENCE": "Zur Quelle wechseln",
"BLOCKED": "Dieses Ticket wird blockiert", "BLOCKED": "Dieses Ticket wird blockiert",
"TITLE_PREVIOUS_ISSUE": "vorheriges Ticket",
"TITLE_NEXT_ISSUE": "nächstes Ticket",
"ACTION_DELETE": "Ticket löschen", "ACTION_DELETE": "Ticket löschen",
"LIGHTBOX_TITLE_BLOKING_ISSUE": "Blockierendes Ticket", "LIGHTBOX_TITLE_BLOKING_ISSUE": "Blockierendes Ticket",
"FIELDS": { "FIELDS": {
@ -1249,28 +1391,6 @@
"TITLE": "Dieses Problem zur User-Story aufwerten", "TITLE": "Dieses Problem zur User-Story aufwerten",
"MESSAGE": "Sind Sie sicher, dass Sie aus diesem Ticket eine neue User-Story erstellen möchten?" "MESSAGE": "Sind Sie sicher, dass Sie aus diesem Ticket eine neue User-Story erstellen möchten?"
}, },
"FILTERS": {
"TITLE": "Filter",
"INPUT_SEARCH_PLACEHOLDER": "Thema oder ref",
"TITLE_ACTION_SEARCH": "Suche",
"ACTION_SAVE_CUSTOM_FILTER": "Als Benutzerfilter speichern",
"BREADCRUMB": "Filter",
"TITLE_BREADCRUMB": "Filter",
"CATEGORIES": {
"TYPE": "Arten",
"STATUS": "Status",
"SEVERITY": "Gewichtung",
"PRIORITIES": "Prioritäten",
"TAGS": "Schlagwörter",
"ASSIGNED_TO": "Zugeordnet",
"CREATED_BY": "Erstellt durch",
"CUSTOM_FILTERS": "Benutzerfilter"
},
"CONFIRM_DELETE": {
"TITLE": "Benutzerfilter löschen",
"MESSAGE": "der Benutzerfilter '{{customFilterName}}'"
}
},
"TABLE": { "TABLE": {
"COLUMNS": { "COLUMNS": {
"TYPE": "Arten", "TYPE": "Arten",
@ -1316,6 +1436,7 @@
"SEARCH": { "SEARCH": {
"PAGE_TITLE": "Suche - {{projectName}}", "PAGE_TITLE": "Suche - {{projectName}}",
"PAGE_DESCRIPTION": "Suchen Sie User-Stories, Tickets, Aufgaben oder Wiki Seiten im Projekt {{projectName}}: {{projectDescription}}", "PAGE_DESCRIPTION": "Suchen Sie User-Stories, Tickets, Aufgaben oder Wiki Seiten im Projekt {{projectName}}: {{projectDescription}}",
"FILTER_EPICS": "Epics",
"FILTER_USER_STORIES": "User-Stories", "FILTER_USER_STORIES": "User-Stories",
"FILTER_ISSUES": "Tickets", "FILTER_ISSUES": "Tickets",
"FILTER_TASKS": "Aufgaben", "FILTER_TASKS": "Aufgaben",
@ -1417,13 +1538,24 @@
"DELETE_LIGHTBOX_TITLE": "Wiki Seite löschen", "DELETE_LIGHTBOX_TITLE": "Wiki Seite löschen",
"DELETE_LINK_TITLE": "Entferne Wiki Link", "DELETE_LINK_TITLE": "Entferne Wiki Link",
"NAVIGATION": { "NAVIGATION": {
"SECTION_NAME": "Links", "HOME": "Hauptseite",
"ACTION_ADD_LINK": "Link hinzufügen" "SECTION_NAME": "BOOKMARKS",
"ACTION_ADD_LINK": "Bookmark hinzufügen",
"ALL_PAGES": "Alle Wiki-Seiten"
}, },
"SUMMARY": { "SUMMARY": {
"TIMES_EDITED": "Zeiten <br />bearbeitet", "TIMES_EDITED": "mal <br />bearbeitet",
"LAST_EDIT": "letzte <br />Bearbeitung", "LAST_EDIT": "letzte <br />Bearbeitung",
"LAST_MODIFICATION": "letzte Änderung" "LAST_MODIFICATION": "letzte Änderung"
},
"SECTION_PAGES_LIST": "Alle Seiten",
"PAGES_LIST_COLUMNS": {
"TITLE": "Titel",
"EDITIONS": "Editions",
"CREATED": "Erstellt",
"MODIFIED": "Geändert",
"CREATOR": "Ersteller",
"LAST_MODIFIER": "Letzter Bearbeiter"
} }
}, },
"HINTS": { "HINTS": {
@ -1447,6 +1579,8 @@
"TASK_CREATED_WITH_US": "{{username}} erstellte die neue Aufgabe {{obj_name}} in {{project_name}}, die zur User-Story {{us_name}} gehört", "TASK_CREATED_WITH_US": "{{username}} erstellte die neue Aufgabe {{obj_name}} in {{project_name}}, die zur User-Story {{us_name}} gehört",
"WIKI_CREATED": "{{username}} erstellte die neue Wiki Seite {{obj_name}} in {{project_name}}", "WIKI_CREATED": "{{username}} erstellte die neue Wiki Seite {{obj_name}} in {{project_name}}",
"MILESTONE_CREATED": "{{username}} erstellte den neuen Sprint {{obj_name}} in {{project_name}}", "MILESTONE_CREATED": "{{username}} erstellte den neuen Sprint {{obj_name}} in {{project_name}}",
"EPIC_CREATED": "{{username}} has created a new epic {{obj_name}} in {{project_name}}",
"EPIC_RELATED_USERSTORY_CREATED": "{{username}} has related the userstory {{related_us_name}} to the epic {{epic_name}} in {{project_name}}",
"NEW_PROJECT": "{{username}} erstellte das Projekt {{project_name}}", "NEW_PROJECT": "{{username}} erstellte das Projekt {{project_name}}",
"MILESTONE_UPDATED": "{{username}} aktualisierte den Sprint {{obj_name}}", "MILESTONE_UPDATED": "{{username}} aktualisierte den Sprint {{obj_name}}",
"US_UPDATED": "{{username}} aktualisierte das Attribut \"{{field_name}}\" der User-Story {{obj_name}}", "US_UPDATED": "{{username}} aktualisierte das Attribut \"{{field_name}}\" der User-Story {{obj_name}}",
@ -1459,9 +1593,13 @@
"TASK_UPDATED_WITH_US": "{{username}} aktualisierte das Attribut \"{{field_name}}\" der Aufgabe {{obj_name}} von User-Story {{us_name}}", "TASK_UPDATED_WITH_US": "{{username}} aktualisierte das Attribut \"{{field_name}}\" der Aufgabe {{obj_name}} von User-Story {{us_name}}",
"TASK_UPDATED_WITH_US_NEW_VALUE": "{{username}} aktualisierte das Attribut \"{{field_name}}\" der Aufgabe {{obj_name}} die zu der User-Story gehört {{us_name}} zu {{new_value}}", "TASK_UPDATED_WITH_US_NEW_VALUE": "{{username}} aktualisierte das Attribut \"{{field_name}}\" der Aufgabe {{obj_name}} die zu der User-Story gehört {{us_name}} zu {{new_value}}",
"WIKI_UPDATED": "{{username}} aktualisierte die WIKI Seite {{obj_name}}", "WIKI_UPDATED": "{{username}} aktualisierte die WIKI Seite {{obj_name}}",
"EPIC_UPDATED": "{{username}} has updated the attribute \"{{field_name}}\" of the epic {{obj_name}}",
"EPIC_UPDATED_WITH_NEW_VALUE": "{{username}} has updated the attribute \"{{field_name}}\" of the epic {{obj_name}} to {{new_value}}",
"EPIC_UPDATED_WITH_NEW_COLOR": "{{username}} has updated the \"{{field_name}}\" of the epic {{obj_name}} to <span class=\"new-color\" style=\"background: {{new_value}}\"></span>",
"NEW_COMMENT_US": "{{username}} schrieb einen Kommentar in der User-Story {{obj_name}}", "NEW_COMMENT_US": "{{username}} schrieb einen Kommentar in der User-Story {{obj_name}}",
"NEW_COMMENT_ISSUE": "{{username}} schrieb einen Kommentar im Ticket {{obj_name}}", "NEW_COMMENT_ISSUE": "{{username}} schrieb einen Kommentar im Ticket {{obj_name}}",
"NEW_COMMENT_TASK": "{{username}} schrieb einen Kommentar in der Aufgabe {{obj_name}}", "NEW_COMMENT_TASK": "{{username}} schrieb einen Kommentar in der Aufgabe {{obj_name}}",
"NEW_COMMENT_EPIC": "{{username}} has commented in the epic {{obj_name}}",
"NEW_MEMBER": "{{project_name}} hat ein neues Mitglied", "NEW_MEMBER": "{{project_name}} hat ein neues Mitglied",
"US_ADDED_MILESTONE": "{{username}} fügte dem Sprint {{sprint_name}} die User-Story {{obj_name}} hinzu", "US_ADDED_MILESTONE": "{{username}} fügte dem Sprint {{sprint_name}} die User-Story {{obj_name}} hinzu",
"US_MOVED": "{{username}} wurde in die Story {{obj_name}} verschoben", "US_MOVED": "{{username}} wurde in die Story {{obj_name}} verschoben",

View File

@ -35,6 +35,8 @@
"ONE_ITEM_LINE": "One item per line...", "ONE_ITEM_LINE": "One item per line...",
"NEW_BULK": "New bulk insert", "NEW_BULK": "New bulk insert",
"RELATED_TASKS": "Related tasks", "RELATED_TASKS": "Related tasks",
"PREVIOUS": "Previous",
"NEXT": "Next",
"LOGOUT": "Logout", "LOGOUT": "Logout",
"EXTERNAL_USER": "an external user", "EXTERNAL_USER": "an external user",
"GENERIC_ERROR": "One of our Oompa Loompas says {{error}}.", "GENERIC_ERROR": "One of our Oompa Loompas says {{error}}.",
@ -45,6 +47,11 @@
"CAPSLOCK_WARNING": "Be careful! You are using capital letters in an input field that is case sensitive.", "CAPSLOCK_WARNING": "Be careful! You are using capital letters in an input field that is case sensitive.",
"CONFIRM_CLOSE_EDIT_MODE_TITLE": "Are you sure you want to close the edit mode?", "CONFIRM_CLOSE_EDIT_MODE_TITLE": "Are you sure you want to close the edit mode?",
"CONFIRM_CLOSE_EDIT_MODE_MESSAGE": "Remember that if you close the edit mode without saving all the changes will be lost", "CONFIRM_CLOSE_EDIT_MODE_MESSAGE": "Remember that if you close the edit mode without saving all the changes will be lost",
"RELATED_USERSTORIES": "Related user stories",
"CARD": {
"ASSIGN_TO": "Assign To",
"EDIT": "Edit card"
},
"FORM_ERRORS": { "FORM_ERRORS": {
"DEFAULT_MESSAGE": "This value seems to be invalid.", "DEFAULT_MESSAGE": "This value seems to be invalid.",
"TYPE_EMAIL": "This value should be a valid email.", "TYPE_EMAIL": "This value should be a valid email.",
@ -115,8 +122,9 @@
"USER_STORY": "User story", "USER_STORY": "User story",
"TASK": "Task", "TASK": "Task",
"ISSUE": "Issue", "ISSUE": "Issue",
"EPIC": "Epic",
"TAGS": { "TAGS": {
"PLACEHOLDER": "I'm it! Tag me...", "PLACEHOLDER": "Enter tag",
"DELETE": "Delete tag", "DELETE": "Delete tag",
"ADD": "Add tag" "ADD": "Add tag"
}, },
@ -196,9 +204,27 @@
"TITLE": "filters", "TITLE": "filters",
"INPUT_PLACEHOLDER": "Subject or reference", "INPUT_PLACEHOLDER": "Subject or reference",
"TITLE_ACTION_FILTER_BUTTON": "search", "TITLE_ACTION_FILTER_BUTTON": "search",
"BREADCRUMB_TITLE": "back to categories", "TITLE": "Filters",
"BREADCRUMB_FILTERS": "Filters", "INPUT_SEARCH_PLACEHOLDER": "Subject or ref",
"BREADCRUMB_STATUS": "status" "TITLE_ACTION_SEARCH": "Search",
"ACTION_SAVE_CUSTOM_FILTER": "save as custom filter",
"PLACEHOLDER_FILTER_NAME": "Write the filter name and press enter",
"APPLIED_FILTERS_NUM": "filters applied",
"CATEGORIES": {
"TYPE": "Type",
"STATUS": "Status",
"SEVERITY": "Severity",
"PRIORITIES": "Priorities",
"TAGS": "Tags",
"ASSIGNED_TO": "Assigned to",
"CREATED_BY": "Created by",
"CUSTOM_FILTERS": "Custom filters",
"EPIC": "Epic"
},
"CONFIRM_DELETE": {
"TITLE": "Delete custom filter",
"MESSAGE": "the custom filter '{{customFilterName}}'"
}
}, },
"WYSIWYG": { "WYSIWYG": {
"H1_BUTTON": "First Level Heading", "H1_BUTTON": "First Level Heading",
@ -228,9 +254,18 @@
"PREVIEW_BUTTON": "Preview", "PREVIEW_BUTTON": "Preview",
"EDIT_BUTTON": "Edit", "EDIT_BUTTON": "Edit",
"ATTACH_FILE_HELP": "Attach files by dragging & dropping on the textarea above.", "ATTACH_FILE_HELP": "Attach files by dragging & dropping on the textarea above.",
"ATTACH_FILE_HELP_SAVE_FIRST": "Save first before if you want to attach files by dragging & dropping on the textarea above.",
"MARKDOWN_HELP": "Markdown syntax help" "MARKDOWN_HELP": "Markdown syntax help"
}, },
"PERMISIONS_CATEGORIES": { "PERMISIONS_CATEGORIES": {
"EPICS": {
"NAME": "Epics",
"VIEW_EPICS": "View epics",
"ADD_EPICS": "Add epics",
"MODIFY_EPICS": "Modify epics",
"COMMENT_EPICS": "Comment epics",
"DELETE_EPICS": "Delete epics"
},
"SPRINTS": { "SPRINTS": {
"NAME": "Sprints", "NAME": "Sprints",
"VIEW_SPRINTS": "View sprints", "VIEW_SPRINTS": "View sprints",
@ -243,6 +278,7 @@
"VIEW_USER_STORIES": "View user stories", "VIEW_USER_STORIES": "View user stories",
"ADD_USER_STORIES": "Add user stories", "ADD_USER_STORIES": "Add user stories",
"MODIFY_USER_STORIES": "Modify user stories", "MODIFY_USER_STORIES": "Modify user stories",
"COMMENT_USER_STORIES": "Comment user stories",
"DELETE_USER_STORIES": "Delete user stories" "DELETE_USER_STORIES": "Delete user stories"
}, },
"TASKS": { "TASKS": {
@ -250,6 +286,7 @@
"VIEW_TASKS": "View tasks", "VIEW_TASKS": "View tasks",
"ADD_TASKS": "Add tasks", "ADD_TASKS": "Add tasks",
"MODIFY_TASKS": "Modify tasks", "MODIFY_TASKS": "Modify tasks",
"COMMENT_TASKS": "Comment tasks",
"DELETE_TASKS": "Delete tasks" "DELETE_TASKS": "Delete tasks"
}, },
"ISSUES": { "ISSUES": {
@ -257,6 +294,7 @@
"VIEW_ISSUES": "View issues", "VIEW_ISSUES": "View issues",
"ADD_ISSUES": "Add issues", "ADD_ISSUES": "Add issues",
"MODIFY_ISSUES": "Modify issues", "MODIFY_ISSUES": "Modify issues",
"COMMENT_ISSUES": "Comment issues",
"DELETE_ISSUES": "Delete issues" "DELETE_ISSUES": "Delete issues"
}, },
"WIKI": { "WIKI": {
@ -366,6 +404,41 @@
"WATCHING_SECTION": "Watching", "WATCHING_SECTION": "Watching",
"DASHBOARD": "Projects Dashboard" "DASHBOARD": "Projects Dashboard"
}, },
"EPICS": {
"TITLE": "EPICS",
"SECTION_NAME": "Epics",
"EPIC": "EPIC",
"PAGE_TITLE": "Epics - {{projectName}}",
"PAGE_DESCRIPTION": "The epics list of the project {{projectName}}: {{projectDescription}}",
"DASHBOARD": {
"ADD": "+ ADD EPIC",
"UNASSIGNED": "Unassigned"
},
"EMPTY": {
"TITLE": "It looks like there aren't any epics yet",
"EXPLANATION": "Epics are items at a higher level that encompass user stories.<br />Epics are at the top of the hierarchy and can be used to group user stories together.",
"HELP": "Learn more about epics"
},
"TABLE": {
"VOTES": "Votes",
"NAME": "Name",
"PROJECT": "Project",
"SPRINT": "Sprint",
"ASSIGNED_TO": "Assigned",
"STATUS": "Status",
"PROGRESS": "Progress",
"VIEW_OPTIONS": "View options"
},
"CREATE": {
"TITLE": "New Epic",
"PLACEHOLDER_DESCRIPTION": "Please add descriptive text to help others better understand this epic",
"TEAM_REQUIREMENT": "Team requirement",
"CLIENT_REQUIREMENT": "Client requirement",
"BLOCKED": "Blocked",
"BLOCKED_NOTE_PLACEHOLDER": "Why is this epic blocked?",
"CREATE_EPIC": "Create epic"
}
},
"PROJECTS": { "PROJECTS": {
"PAGE_TITLE": "My projects - Taiga", "PAGE_TITLE": "My projects - Taiga",
"PAGE_DESCRIPTION": "A list with all your projects, you can reorder or create a new one.", "PAGE_DESCRIPTION": "A list with all your projects, you can reorder or create a new one.",
@ -402,7 +475,8 @@
"ADMIN": { "ADMIN": {
"COMMON": { "COMMON": {
"TITLE_ACTION_EDIT_VALUE": "Edit value", "TITLE_ACTION_EDIT_VALUE": "Edit value",
"TITLE_ACTION_DELETE_VALUE": "Delete value" "TITLE_ACTION_DELETE_VALUE": "Delete value",
"TITLE_ACTION_DELETE_TAG": "Delete tag"
}, },
"HELP": "Do you need help? Check out our support page!", "HELP": "Do you need help? Check out our support page!",
"PROJECT_DEFAULT_VALUES": { "PROJECT_DEFAULT_VALUES": {
@ -435,6 +509,8 @@
"TITLE": "Modules", "TITLE": "Modules",
"ENABLE": "Enable", "ENABLE": "Enable",
"DISABLE": "Disable", "DISABLE": "Disable",
"EPICS": "Epics",
"EPICS_DESCRIPTION": "Visualize and manage the most strategic part of your project",
"BACKLOG": "Backlog", "BACKLOG": "Backlog",
"BACKLOG_DESCRIPTION": "Manage your user stories to maintain an organized view of upcoming and prioritized work.", "BACKLOG_DESCRIPTION": "Manage your user stories to maintain an organized view of upcoming and prioritized work.",
"NUMBER_SPRINTS": "Expected number of sprints", "NUMBER_SPRINTS": "Expected number of sprints",
@ -497,6 +573,7 @@
"REGENERATE_SUBTITLE": "You going to change the CSV data access url. The previous url will be disabled. Are you sure?" "REGENERATE_SUBTITLE": "You going to change the CSV data access url. The previous url will be disabled. Are you sure?"
}, },
"CSV": { "CSV": {
"SECTION_TITLE_EPIC": "epics reports",
"SECTION_TITLE_US": "user stories reports", "SECTION_TITLE_US": "user stories reports",
"SECTION_TITLE_TASK": "tasks reports", "SECTION_TITLE_TASK": "tasks reports",
"SECTION_TITLE_ISSUE": "issues reports", "SECTION_TITLE_ISSUE": "issues reports",
@ -509,6 +586,8 @@
"CUSTOM_FIELDS": { "CUSTOM_FIELDS": {
"TITLE": "Custom Fields", "TITLE": "Custom Fields",
"SUBTITLE": "Specify the custom fields for your user stories, tasks and issues", "SUBTITLE": "Specify the custom fields for your user stories, tasks and issues",
"EPIC_DESCRIPTION": "Epics custom fields",
"EPIC_ADD": "Add a custom field in epics",
"US_DESCRIPTION": "User stories custom fields", "US_DESCRIPTION": "User stories custom fields",
"US_ADD": "Add a custom field in user stories", "US_ADD": "Add a custom field in user stories",
"TASK_DESCRIPTION": "Tasks custom fields", "TASK_DESCRIPTION": "Tasks custom fields",
@ -546,7 +625,8 @@
"PROJECT_VALUES_STATUS": { "PROJECT_VALUES_STATUS": {
"TITLE": "Status", "TITLE": "Status",
"SUBTITLE": "Specify the statuses your user stories, tasks and issues will go through", "SUBTITLE": "Specify the statuses your user stories, tasks and issues will go through",
"US_TITLE": "US Statuses", "EPIC_TITLE": "Epic Statuses",
"US_TITLE": "User Story Statuses",
"TASK_TITLE": "Task Statuses", "TASK_TITLE": "Task Statuses",
"ISSUE_TITLE": "Issue Statuses" "ISSUE_TITLE": "Issue Statuses"
}, },
@ -556,6 +636,17 @@
"ISSUE_TITLE": "Issues types", "ISSUE_TITLE": "Issues types",
"ACTION_ADD": "Add new {{objName}}" "ACTION_ADD": "Add new {{objName}}"
}, },
"PROJECT_VALUES_TAGS": {
"TITLE": "Tags",
"SUBTITLE": "View and edit the color of your tags",
"EMPTY": "Currently there are no tags",
"EMPTY_SEARCH": "It looks like nothing was found with your search criteria",
"ACTION_ADD": "Add tag",
"NEW_TAG": "New tag",
"MIXING_HELP_TEXT": "Select the tags that you want to merge",
"MIXING_MERGE": "Merge Tags",
"SELECTED": "Selected"
},
"ROLES": { "ROLES": {
"PAGE_TITLE": "Roles - {{projectName}}", "PAGE_TITLE": "Roles - {{projectName}}",
"WARNING_NO_ROLE": "Be careful, no role in your project will be able to estimate the point value for user stories", "WARNING_NO_ROLE": "Be careful, no role in your project will be able to estimate the point value for user stories",
@ -588,6 +679,10 @@
"SECTION_NAME": "Github", "SECTION_NAME": "Github",
"PAGE_TITLE": "Github - {{projectName}}" "PAGE_TITLE": "Github - {{projectName}}"
}, },
"GOGS": {
"SECTION_NAME": "Gogs",
"PAGE_TITLE": "Gogs - {{projectName}}"
},
"WEBHOOKS": { "WEBHOOKS": {
"PAGE_TITLE": "Webhooks - {{projectName}}", "PAGE_TITLE": "Webhooks - {{projectName}}",
"SECTION_NAME": "Webhooks", "SECTION_NAME": "Webhooks",
@ -643,13 +738,14 @@
"DEFAULT_DELETE_MESSAGE": "the invitation to {{email}}" "DEFAULT_DELETE_MESSAGE": "the invitation to {{email}}"
}, },
"DEFAULT_VALUES": { "DEFAULT_VALUES": {
"LABEL_EPIC_STATUS": "Default value for epic status selector",
"LABEL_US_STATUS": "Default value for user story status selector",
"LABEL_POINTS": "Default value for points selector", "LABEL_POINTS": "Default value for points selector",
"LABEL_US": "Default value for US status selector",
"LABEL_TASK_STATUS": "Default value for task status selector", "LABEL_TASK_STATUS": "Default value for task status selector",
"LABEL_PRIORITY": "Default value for priority selector",
"LABEL_SEVERITY": "Default value for severity selector",
"LABEL_ISSUE_TYPE": "Default value for issue type selector", "LABEL_ISSUE_TYPE": "Default value for issue type selector",
"LABEL_ISSUE_STATUS": "Default value for issue status selector" "LABEL_ISSUE_STATUS": "Default value for issue status selector",
"LABEL_PRIORITY": "Default value for priority selector",
"LABEL_SEVERITY": "Default value for severity selector"
}, },
"STATUS": { "STATUS": {
"PLACEHOLDER_WRITE_STATUS_NAME": "Write a name for the new status" "PLACEHOLDER_WRITE_STATUS_NAME": "Write a name for the new status"
@ -681,7 +777,8 @@
"PRIORITIES": "Priorities", "PRIORITIES": "Priorities",
"SEVERITIES": "Severities", "SEVERITIES": "Severities",
"TYPES": "Types", "TYPES": "Types",
"CUSTOM_FIELDS": "Custom fields" "CUSTOM_FIELDS": "Custom fields",
"TAGS": "Tags"
}, },
"SUBMENU_PROJECT_PROFILE": { "SUBMENU_PROJECT_PROFILE": {
"TITLE": "Project Profile" "TITLE": "Project Profile"
@ -751,6 +848,8 @@
"FILTER_TYPE_ALL_TITLE": "Show all", "FILTER_TYPE_ALL_TITLE": "Show all",
"FILTER_TYPE_PROJECTS": "Projects", "FILTER_TYPE_PROJECTS": "Projects",
"FILTER_TYPE_PROJECT_TITLES": "Show only projects", "FILTER_TYPE_PROJECT_TITLES": "Show only projects",
"FILTER_TYPE_EPICS": "Epics",
"FILTER_TYPE_EPIC_TITLES": "Show only epics",
"FILTER_TYPE_USER_STORIES": "Stories", "FILTER_TYPE_USER_STORIES": "Stories",
"FILTER_TYPE_USER_STORIES_TITLES": "Show only user stories", "FILTER_TYPE_USER_STORIES_TITLES": "Show only user stories",
"FILTER_TYPE_TASKS": "Tasks", "FILTER_TYPE_TASKS": "Tasks",
@ -950,8 +1049,8 @@
"CREATE_MEMBER": { "CREATE_MEMBER": {
"PLACEHOLDER_INVITATION_TEXT": "(Optional) Add a personalized text to the invitation. Tell something lovely to your new members ;-)", "PLACEHOLDER_INVITATION_TEXT": "(Optional) Add a personalized text to the invitation. Tell something lovely to your new members ;-)",
"PLACEHOLDER_TYPE_EMAIL": "Type an Email", "PLACEHOLDER_TYPE_EMAIL": "Type an Email",
"LIMIT_USERS_WARNING_MESSAGE_FOR_OWNER": "Unfortunately, this project can't have more than <strong>{{maxMembers}}</strong> members.<br> If you would like to increase the current limit, please contact the administrator.", "LIMIT_USERS_WARNING_MESSAGE_FOR_OWNER": "You are about to reach the maximum number of members allowed for this project, <strong>{{maxMembers}}</strong> members. If you would like to increase the current limit, please contact the administrator.",
"LIMIT_USERS_WARNING_MESSAGE": "Unfortunately, this project can't have more than <strong>{{maxMembers}}</strong> members." "LIMIT_USERS_WARNING_MESSAGE": "You are about to reach the maximum number of members allowed for this project, <strong>{{maxMembers}}</strong> members."
}, },
"LEAVE_PROJECT_WARNING": { "LEAVE_PROJECT_WARNING": {
"TITLE": "Unfortunately, this project can't be left without an owner", "TITLE": "Unfortunately, this project can't be left without an owner",
@ -970,10 +1069,30 @@
"BUTTON": "Ask this project member to become the new project owner" "BUTTON": "Ask this project member to become the new project owner"
} }
}, },
"EPIC": {
"PAGE_TITLE": "{{epicSubject}} - Epic {{epicRef}} - {{projectName}}",
"PAGE_DESCRIPTION": "Status: {{epicStatus }}. Description: {{epicDescription}}",
"SECTION_NAME": "Epic",
"TITLE_LIGHTBOX_UNLINK_RELATED_USERSTORY": "Unlink related userstory",
"MSG_LIGHTBOX_UNLINK_RELATED_USERSTORY": "It will delete the link to the related userstory '{{subject}}'",
"ERROR_UNLINK_RELATED_USERSTORY": "We have not been able to unlink: {{errorMessage}}",
"CREATE_RELATED_USERSTORIES": "Create a relationship with",
"NEW_USERSTORY": "New user story",
"EXISTING_USERSTORY": "Existing user story",
"CHOOSE_PROJECT_FOR_CREATION": "What's the project?",
"SUBJECT": "Subject",
"SUBJECT_BULK_MODE": "Subject (bulk insert)",
"CHOOSE_PROJECT_FROM": "What's the project?",
"CHOOSE_USERSTORY": "What's the user story?",
"NO_USERSTORIES": "This project has no User Stories yet. Please select another project.",
"FILTER_USERSTORIES": "Filter user stories",
"LIGHTBOX_TITLE_BLOKING_EPIC": "Blocking epic",
"ACTION_DELETE": "Delete epic"
},
"US": { "US": {
"PAGE_TITLE": "{{userStorySubject}} - User Story {{userStoryRef}} - {{projectName}}", "PAGE_TITLE": "{{userStorySubject}} - User Story {{userStoryRef}} - {{projectName}}",
"PAGE_DESCRIPTION": "Status: {{userStoryStatus }}. Completed {{userStoryProgressPercentage}}% ({{userStoryClosedTasks}} of {{userStoryTotalTasks}} tasks closed). Points: {{userStoryPoints}}. Description: {{userStoryDescription}}", "PAGE_DESCRIPTION": "Status: {{userStoryStatus }}. Completed {{userStoryProgressPercentage}}% ({{userStoryClosedTasks}} of {{userStoryTotalTasks}} tasks closed). Points: {{userStoryPoints}}. Description: {{userStoryDescription}}",
"SECTION_NAME": "User story details", "SECTION_NAME": "User story",
"LINK_TASKBOARD": "Taskboard", "LINK_TASKBOARD": "Taskboard",
"TITLE_LINK_TASKBOARD": "Go to the taskboard", "TITLE_LINK_TASKBOARD": "Go to the taskboard",
"TOTAL_POINTS": "total points", "TOTAL_POINTS": "total points",
@ -984,8 +1103,6 @@
"EXTERNAL_REFERENCE": "This US has been created from", "EXTERNAL_REFERENCE": "This US has been created from",
"GO_TO_EXTERNAL_REFERENCE": "Go to origin", "GO_TO_EXTERNAL_REFERENCE": "Go to origin",
"BLOCKED": "This user story is blocked", "BLOCKED": "This user story is blocked",
"PREVIOUS": "previous user story",
"NEXT": "next user story",
"TITLE_DELETE_ACTION": "Delete User Story", "TITLE_DELETE_ACTION": "Delete User Story",
"LIGHTBOX_TITLE_BLOKING_US": "Blocking us", "LIGHTBOX_TITLE_BLOKING_US": "Blocking us",
"TASK_COMPLETED": "{{totalClosedTasks}}/{{totalTasks}} tasks completed", "TASK_COMPLETED": "{{totalClosedTasks}}/{{totalTasks}} tasks completed",
@ -1010,28 +1127,47 @@
} }
}, },
"COMMENTS": { "COMMENTS": {
"DELETED_INFO": "Comment deleted by {{user}} on {{date}}", "DELETED_INFO": "Comment deleted by {{user}}",
"TITLE": "Comments", "TITLE": "Comments",
"COMMENTS_COUNT": "{{comments}} Comments",
"ORDER": "Order",
"OLDER_FIRST": "Older first",
"RECENT_FIRST": "Recent first",
"COMMENT": "Comment", "COMMENT": "Comment",
"EDIT_COMMENT": "Edit comment",
"EDITED_COMMENT": "Edited:",
"SHOW_HISTORY": "View historic",
"TYPE_NEW_COMMENT": "Type a new comment here", "TYPE_NEW_COMMENT": "Type a new comment here",
"SHOW_DELETED": "Show deleted comment", "SHOW_DELETED": "Show deleted comment",
"HIDE_DELETED": "Hide deleted comment", "HIDE_DELETED": "Hide deleted comment",
"DELETE": "Delete comment", "DELETE": "Delete comment",
"RESTORE": "Restore comment" "RESTORE": "Restore comment",
"HISTORY": {
"TITLE": "Activity"
}
}, },
"ACTIVITY": { "ACTIVITY": {
"SHOW_ACTIVITY": "Show activity", "SHOW_ACTIVITY": "Show activity",
"DATETIME": "DD MMM YYYY HH:mm", "DATETIME": "DD MMM YYYY HH:mm",
"SHOW_MORE": "+ Show previous entries ({{showMore}} more)", "SHOW_MORE": "+ Show previous entries ({{showMore}} more)",
"TITLE": "Activity", "TITLE": "Activity",
"ACTIVITIES_COUNT": "{{activities}} Activities",
"REMOVED": "removed", "REMOVED": "removed",
"ADDED": "added", "ADDED": "added",
"US_POINTS": "US points ({{name}})", "TAGS_ADDED": "tags added:",
"NEW_ATTACHMENT": "new attachment", "TAGS_REMOVED": "tags removed:",
"DELETED_ATTACHMENT": "deleted attachment", "US_POINTS": "{{role}} points",
"UPDATED_ATTACHMENT": "updated attachment {{filename}}", "NEW_ATTACHMENT": "new attachment:",
"DELETED_CUSTOM_ATTRIBUTE": "deleted custom attribute", "DELETED_ATTACHMENT": "deleted attachment:",
"UPDATED_ATTACHMENT": "updated attachment ({{filename}}): ",
"CREATED_CUSTOM_ATTRIBUTE": "created custom attribute",
"UPDATED_CUSTOM_ATTRIBUTE": "updated custom attribute",
"SIZE_CHANGE": "Made {size, plural, one{one change} other{# changes}}", "SIZE_CHANGE": "Made {size, plural, one{one change} other{# changes}}",
"BECAME_DEPRECATED": "became deprecated",
"BECAME_UNDEPRECATED": "became undeprecated",
"TEAM_REQUIREMENT": "Team Requirement",
"CLIENT_REQUIREMENT": "Client Requirement",
"BLOCKED": "Blocked",
"VALUES": { "VALUES": {
"YES": "yes", "YES": "yes",
"NO": "no", "NO": "no",
@ -1063,12 +1199,14 @@
"TAGS": "tags", "TAGS": "tags",
"ATTACHMENTS": "attachments", "ATTACHMENTS": "attachments",
"IS_DEPRECATED": "is deprecated", "IS_DEPRECATED": "is deprecated",
"IS_NOT_DEPRECATED": "is not deprecated",
"ORDER": "order", "ORDER": "order",
"BACKLOG_ORDER": "backlog order", "BACKLOG_ORDER": "backlog order",
"SPRINT_ORDER": "sprint order", "SPRINT_ORDER": "sprint order",
"KANBAN_ORDER": "kanban order", "KANBAN_ORDER": "kanban order",
"TASKBOARD_ORDER": "taskboard order", "TASKBOARD_ORDER": "taskboard order",
"US_ORDER": "us order" "US_ORDER": "us order",
"COLOR": "color"
} }
}, },
"BACKLOG": { "BACKLOG": {
@ -1120,7 +1258,8 @@
"CLOSED_TASKS": "closed<br />tasks", "CLOSED_TASKS": "closed<br />tasks",
"IOCAINE_DOSES": "iocaine<br />doses", "IOCAINE_DOSES": "iocaine<br />doses",
"SHOW_STATISTICS_TITLE": "Show statistics", "SHOW_STATISTICS_TITLE": "Show statistics",
"TOGGLE_BAKLOG_GRAPH": "Show/Hide burndown graph" "TOGGLE_BAKLOG_GRAPH": "Show/Hide burndown graph",
"POINTS_PER_ROLE": "Points per role"
}, },
"SUMMARY": { "SUMMARY": {
"PROJECT_POINTS": "project<br />points", "PROJECT_POINTS": "project<br />points",
@ -1133,9 +1272,7 @@
"TITLE": "Filters", "TITLE": "Filters",
"REMOVE": "Remove Filters", "REMOVE": "Remove Filters",
"HIDE": "Hide Filters", "HIDE": "Hide Filters",
"SHOW": "Show Filters", "SHOW": "Show Filters"
"FILTER_CATEGORY_STATUS": "Status",
"FILTER_CATEGORY_TAGS": "Tags"
}, },
"SPRINTS": { "SPRINTS": {
"TITLE": "SPRINTS", "TITLE": "SPRINTS",
@ -1190,7 +1327,7 @@
"TASK": { "TASK": {
"PAGE_TITLE": "{{taskSubject}} - Task {{taskRef}} - {{projectName}}", "PAGE_TITLE": "{{taskSubject}} - Task {{taskRef}} - {{projectName}}",
"PAGE_DESCRIPTION": "Status: {{taskStatus }}. Description: {{taskDescription}}", "PAGE_DESCRIPTION": "Status: {{taskStatus }}. Description: {{taskDescription}}",
"SECTION_NAME": "Task details", "SECTION_NAME": "Task",
"LINK_TASKBOARD": "Taskboard", "LINK_TASKBOARD": "Taskboard",
"TITLE_LINK_TASKBOARD": "Go to the taskboard", "TITLE_LINK_TASKBOARD": "Go to the taskboard",
"PLACEHOLDER_SUBJECT": "Type the new task subject", "PLACEHOLDER_SUBJECT": "Type the new task subject",
@ -1200,8 +1337,6 @@
"ORIGIN_US": "This task has been created from", "ORIGIN_US": "This task has been created from",
"TITLE_LINK_GO_ORIGIN": "Go to user story", "TITLE_LINK_GO_ORIGIN": "Go to user story",
"BLOCKED": "This task is blocked", "BLOCKED": "This task is blocked",
"PREVIOUS": "previous task",
"NEXT": "next task",
"TITLE_DELETE_ACTION": "Delete Task", "TITLE_DELETE_ACTION": "Delete Task",
"LIGHTBOX_TITLE_BLOKING_TASK": "Blocking task", "LIGHTBOX_TITLE_BLOKING_TASK": "Blocking task",
"FIELDS": { "FIELDS": {
@ -1239,16 +1374,13 @@
"PAGE_TITLE": "Issues - {{projectName}}", "PAGE_TITLE": "Issues - {{projectName}}",
"PAGE_DESCRIPTION": "The issues list panel of the project {{projectName}}: {{projectDescription}}", "PAGE_DESCRIPTION": "The issues list panel of the project {{projectName}}: {{projectDescription}}",
"LIST_SECTION_NAME": "Issues", "LIST_SECTION_NAME": "Issues",
"SECTION_NAME": "Issue details", "SECTION_NAME": "Issue",
"ACTION_NEW_ISSUE": "+ NEW ISSUE", "ACTION_NEW_ISSUE": "+ NEW ISSUE",
"ACTION_PROMOTE_TO_US": "Promote to User Story", "ACTION_PROMOTE_TO_US": "Promote to User Story",
"PLACEHOLDER_FILTER_NAME": "Write the filter name and press enter",
"PROMOTED": "This issue has been promoted to US:", "PROMOTED": "This issue has been promoted to US:",
"EXTERNAL_REFERENCE": "This issue has been created from", "EXTERNAL_REFERENCE": "This issue has been created from",
"GO_TO_EXTERNAL_REFERENCE": "Go to origin", "GO_TO_EXTERNAL_REFERENCE": "Go to origin",
"BLOCKED": "This issue is blocked", "BLOCKED": "This issue is blocked",
"TITLE_PREVIOUS_ISSUE": "previous issue",
"TITLE_NEXT_ISSUE": "next issue",
"ACTION_DELETE": "Delete issue", "ACTION_DELETE": "Delete issue",
"LIGHTBOX_TITLE_BLOKING_ISSUE": "Blocking issue", "LIGHTBOX_TITLE_BLOKING_ISSUE": "Blocking issue",
"FIELDS": { "FIELDS": {
@ -1260,28 +1392,6 @@
"TITLE": "Promote this issue to a new user story", "TITLE": "Promote this issue to a new user story",
"MESSAGE": "Are you sure you want to create a new US from this Issue?" "MESSAGE": "Are you sure you want to create a new US from this Issue?"
}, },
"FILTERS": {
"TITLE": "Filters",
"INPUT_SEARCH_PLACEHOLDER": "Subject or ref",
"TITLE_ACTION_SEARCH": "Search",
"ACTION_SAVE_CUSTOM_FILTER": "save as custom filter",
"BREADCRUMB": "Filters",
"TITLE_BREADCRUMB": "Filters",
"CATEGORIES": {
"TYPE": "Type",
"STATUS": "Status",
"SEVERITY": "Severity",
"PRIORITIES": "Priorities",
"TAGS": "Tags",
"ASSIGNED_TO": "Assigned to",
"CREATED_BY": "Created by",
"CUSTOM_FILTERS": "Custom filters"
},
"CONFIRM_DELETE": {
"TITLE": "Delete custom filter",
"MESSAGE": "the custom filter '{{customFilterName}}'"
}
},
"TABLE": { "TABLE": {
"COLUMNS": { "COLUMNS": {
"TYPE": "Type", "TYPE": "Type",
@ -1327,6 +1437,7 @@
"SEARCH": { "SEARCH": {
"PAGE_TITLE": "Search - {{projectName}}", "PAGE_TITLE": "Search - {{projectName}}",
"PAGE_DESCRIPTION": "Search anything, user stories, issues, tasks or wiki pages, in the project {{projectName}}: {{projectDescription}}", "PAGE_DESCRIPTION": "Search anything, user stories, issues, tasks or wiki pages, in the project {{projectName}}: {{projectDescription}}",
"FILTER_EPICS": "Epics",
"FILTER_USER_STORIES": "User Stories", "FILTER_USER_STORIES": "User Stories",
"FILTER_ISSUES": "Issues", "FILTER_ISSUES": "Issues",
"FILTER_TASKS": "Tasks", "FILTER_TASKS": "Tasks",
@ -1428,13 +1539,24 @@
"DELETE_LIGHTBOX_TITLE": "Delete Wiki Page", "DELETE_LIGHTBOX_TITLE": "Delete Wiki Page",
"DELETE_LINK_TITLE": "Delete Wiki link", "DELETE_LINK_TITLE": "Delete Wiki link",
"NAVIGATION": { "NAVIGATION": {
"SECTION_NAME": "Links", "HOME": "Main Page",
"ACTION_ADD_LINK": "Add link" "SECTION_NAME": "BOOKMARKS",
"ACTION_ADD_LINK": "Add bookmark",
"ALL_PAGES": "All wiki pages"
}, },
"SUMMARY": { "SUMMARY": {
"TIMES_EDITED": "times <br />edited", "TIMES_EDITED": "times <br />edited",
"LAST_EDIT": "last <br />edit", "LAST_EDIT": "last <br />edit",
"LAST_MODIFICATION": "last modification" "LAST_MODIFICATION": "last modification"
},
"SECTION_PAGES_LIST": "All pages",
"PAGES_LIST_COLUMNS": {
"TITLE": "Title",
"EDITIONS": "Editions",
"CREATED": "Created",
"MODIFIED": "Modified",
"CREATOR": "Creator",
"LAST_MODIFIER": "Last modifier"
} }
}, },
"HINTS": { "HINTS": {
@ -1458,6 +1580,8 @@
"TASK_CREATED_WITH_US": "{{username}} has created a new task {{obj_name}} in {{project_name}} which belongs to the US {{us_name}}", "TASK_CREATED_WITH_US": "{{username}} has created a new task {{obj_name}} in {{project_name}} which belongs to the US {{us_name}}",
"WIKI_CREATED": "{{username}} has created a new wiki page {{obj_name}} in {{project_name}}", "WIKI_CREATED": "{{username}} has created a new wiki page {{obj_name}} in {{project_name}}",
"MILESTONE_CREATED": "{{username}} has created a new sprint {{obj_name}} in {{project_name}}", "MILESTONE_CREATED": "{{username}} has created a new sprint {{obj_name}} in {{project_name}}",
"EPIC_CREATED": "{{username}} has created a new epic {{obj_name}} in {{project_name}}",
"EPIC_RELATED_USERSTORY_CREATED": "{{username}} has related the userstory {{related_us_name}} to the epic {{epic_name}} in {{project_name}}",
"NEW_PROJECT": "{{username}} created the project {{project_name}}", "NEW_PROJECT": "{{username}} created the project {{project_name}}",
"MILESTONE_UPDATED": "{{username}} has updated the sprint {{obj_name}}", "MILESTONE_UPDATED": "{{username}} has updated the sprint {{obj_name}}",
"US_UPDATED": "{{username}} has updated the attribute \"{{field_name}}\" of the US {{obj_name}}", "US_UPDATED": "{{username}} has updated the attribute \"{{field_name}}\" of the US {{obj_name}}",
@ -1470,9 +1594,13 @@
"TASK_UPDATED_WITH_US": "{{username}} has updated the attribute \"{{field_name}}\" of the task {{obj_name}} which belongs to the US {{us_name}}", "TASK_UPDATED_WITH_US": "{{username}} has updated the attribute \"{{field_name}}\" of the task {{obj_name}} which belongs to the US {{us_name}}",
"TASK_UPDATED_WITH_US_NEW_VALUE": "{{username}} has updated the attribute \"{{field_name}}\" of the task {{obj_name}} which belongs to the US {{us_name}} to {{new_value}}", "TASK_UPDATED_WITH_US_NEW_VALUE": "{{username}} has updated the attribute \"{{field_name}}\" of the task {{obj_name}} which belongs to the US {{us_name}} to {{new_value}}",
"WIKI_UPDATED": "{{username}} has updated the wiki page {{obj_name}}", "WIKI_UPDATED": "{{username}} has updated the wiki page {{obj_name}}",
"EPIC_UPDATED": "{{username}} has updated the attribute \"{{field_name}}\" of the epic {{obj_name}}",
"EPIC_UPDATED_WITH_NEW_VALUE": "{{username}} has updated the attribute \"{{field_name}}\" of the epic {{obj_name}} to {{new_value}}",
"EPIC_UPDATED_WITH_NEW_COLOR": "{{username}} has updated the \"{{field_name}}\" of the epic {{obj_name}} to <span class=\"new-color\" style=\"background: {{new_value}}\"></span>",
"NEW_COMMENT_US": "{{username}} has commented in the US {{obj_name}}", "NEW_COMMENT_US": "{{username}} has commented in the US {{obj_name}}",
"NEW_COMMENT_ISSUE": "{{username}} has commented in the issue {{obj_name}}", "NEW_COMMENT_ISSUE": "{{username}} has commented in the issue {{obj_name}}",
"NEW_COMMENT_TASK": "{{username}} has commented in the task {{obj_name}}", "NEW_COMMENT_TASK": "{{username}} has commented in the task {{obj_name}}",
"NEW_COMMENT_EPIC": "{{username}} has commented in the epic {{obj_name}}",
"NEW_MEMBER": "{{project_name}} has a new member", "NEW_MEMBER": "{{project_name}} has a new member",
"US_ADDED_MILESTONE": "{{username}} has added the US {{obj_name}} to {{sprint_name}}", "US_ADDED_MILESTONE": "{{username}} has added the US {{obj_name}} to {{sprint_name}}",
"US_MOVED": "{{username}} has moved the US {{obj_name}}", "US_MOVED": "{{username}} has moved the US {{obj_name}}",

View File

@ -35,16 +35,23 @@
"ONE_ITEM_LINE": "Un elemento por línea...", "ONE_ITEM_LINE": "Un elemento por línea...",
"NEW_BULK": "Nueva inserción en bloque", "NEW_BULK": "Nueva inserción en bloque",
"RELATED_TASKS": "Tareas relacionadas", "RELATED_TASKS": "Tareas relacionadas",
"PREVIOUS": "Previous",
"NEXT": "Siguiente",
"LOGOUT": "Cerrar sesión", "LOGOUT": "Cerrar sesión",
"EXTERNAL_USER": "un usuario externo", "EXTERNAL_USER": "un usuario externo",
"GENERIC_ERROR": "Uno de nuestros Oompa Loompas dice {{error}}.", "GENERIC_ERROR": "Uno de nuestros Oompa Loompas dice {{error}}.",
"IOCAINE_TEXT": "¿Te sientes fuera de tu zona de confort en una tarea? Asegúrate de que los demás están al tanto de ello, marca el check de la Iocaína al editar una tarea. Igual eu era posible llegar a ser inmune a este veneno mortal a base de consumir pequeñas dosis a lo largo del tiempo, es posible conseguir mejor en lo que estás haciendo si afrontas de vez en cuando esta clase de retos!", "IOCAINE_TEXT": "¿Te sientes fuera de tu zona de confort en una tarea? Asegúrate de que los demás están al tanto de ello, marca el check de la Iocaína al editar una tarea. Igual eu era posible llegar a ser inmune a este veneno mortal a base de consumir pequeñas dosis a lo largo del tiempo, es posible conseguir mejor en lo que estás haciendo si afrontas de vez en cuando esta clase de retos!",
"CLIENT_REQUIREMENT": "Requerimiento de cliente es un nuevo requisito que no se esperaba y es necesario que forme parte del proyecto.", "CLIENT_REQUIREMENT": "Requerimiento de cliente es un nuevo requisito que no se esperaba y es necesario que forme parte del proyecto.",
"TEAM_REQUIREMENT": "Requerimiento del equipo es un nuevo requisito que debe existir en el proyecto pero que no conllevará ningún coste para el cliente.", "TEAM_REQUIREMENT": "Requerimiento del equipo es un nuevo requisito que debe existir en el proyecto pero que no conllevará ningún coste para el cliente.",
"OWNER": "Project Owner", "OWNER": "Dueño del proyecto",
"CAPSLOCK_WARNING": "Be careful! You are using capital letters in an input field that is case sensitive.", "CAPSLOCK_WARNING": "¡Cuidado!. Esta usando mayusculas en un campo sensible a mayusculas",
"CONFIRM_CLOSE_EDIT_MODE_TITLE": "Are you sure you want to close the edit mode?", "CONFIRM_CLOSE_EDIT_MODE_TITLE": "¿Seguro que desea cerrar el modo de edición?",
"CONFIRM_CLOSE_EDIT_MODE_MESSAGE": "Remember that if you close the edit mode without saving all the changes will be lost", "CONFIRM_CLOSE_EDIT_MODE_MESSAGE": "Recuerde que si cierra el modo de edicion sin guardar todos los cambios se perderán",
"RELATED_USERSTORIES": "Related user stories",
"CARD": {
"ASSIGN_TO": "Assign To",
"EDIT": "Edit card"
},
"FORM_ERRORS": { "FORM_ERRORS": {
"DEFAULT_MESSAGE": "Este valor parece inválido.", "DEFAULT_MESSAGE": "Este valor parece inválido.",
"TYPE_EMAIL": "El valor debe ser un email.", "TYPE_EMAIL": "El valor debe ser un email.",
@ -69,8 +76,8 @@
"MAX_CHECK": "Debes seleccionar %s o menos.", "MAX_CHECK": "Debes seleccionar %s o menos.",
"RANGE_CHECK": "Debes seleccionar de %s a %s.", "RANGE_CHECK": "Debes seleccionar de %s a %s.",
"EQUAL_TO": "Este valor debe ser el mismo.", "EQUAL_TO": "Este valor debe ser el mismo.",
"LINEWIDTH": "One or more lines is perhaps too long. Try to keep under %s characters.", "LINEWIDTH": "Una o más líneas es tal vez demasiado tiempo. Trate de mantener bajo %s caracteres.",
"PIKADAY": "Invalid date format, please use DD MMM YYYY (like 23 Mar 1984)" "PIKADAY": "Formato de fecha no válida, por favor utilice DD MMM AAAA (como 23 Mar 1984)"
}, },
"PICKERDATE": { "PICKERDATE": {
"FORMAT": "DD MMM YYYY", "FORMAT": "DD MMM YYYY",
@ -115,8 +122,9 @@
"USER_STORY": "Historia de usuario", "USER_STORY": "Historia de usuario",
"TASK": "Tarea", "TASK": "Tarea",
"ISSUE": "Petición", "ISSUE": "Petición",
"EPIC": "Epic",
"TAGS": { "TAGS": {
"PLACEHOLDER": "¿Qué soy? Etiquétame...", "PLACEHOLDER": "Enter tag",
"DELETE": "Borrar etiqueta", "DELETE": "Borrar etiqueta",
"ADD": "Añadir etiqueta" "ADD": "Añadir etiqueta"
}, },
@ -193,12 +201,29 @@
"CONFIRM_DELETE": "Se borrarán todos los valores de este atributo personalizado. \n¿Estás seguro de que quieres continuar?" "CONFIRM_DELETE": "Se borrarán todos los valores de este atributo personalizado. \n¿Estás seguro de que quieres continuar?"
}, },
"FILTERS": { "FILTERS": {
"TITLE": "filtros", "TITLE": "Filtros",
"INPUT_PLACEHOLDER": "Asunto o referencia", "INPUT_PLACEHOLDER": "Asunto o referencia",
"TITLE_ACTION_FILTER_BUTTON": "busqueda", "TITLE_ACTION_FILTER_BUTTON": "busqueda",
"BREADCRUMB_TITLE": "Regresar a categorias", "INPUT_SEARCH_PLACEHOLDER": "Asunto o referencia",
"BREADCRUMB_FILTERS": "Filtros", "TITLE_ACTION_SEARCH": "Buscar",
"BREADCRUMB_STATUS": "estado" "ACTION_SAVE_CUSTOM_FILTER": "guardar como filtro personalizado",
"PLACEHOLDER_FILTER_NAME": "Escribe un nombre para el filtro y pulsa enter",
"APPLIED_FILTERS_NUM": "filters applied",
"CATEGORIES": {
"TYPE": "Tipo",
"STATUS": "Estado",
"SEVERITY": "Gravedad",
"PRIORITIES": "Prioridades",
"TAGS": "Etiquetas",
"ASSIGNED_TO": "Asignado a",
"CREATED_BY": "Creada por",
"CUSTOM_FILTERS": "Filtros personalizados",
"EPIC": "Epic"
},
"CONFIRM_DELETE": {
"TITLE": "Eliminar filtros personalizados",
"MESSAGE": "el filtro personalizado '{{customFilterName}}'"
}
}, },
"WYSIWYG": { "WYSIWYG": {
"H1_BUTTON": "Título de primer nivel", "H1_BUTTON": "Título de primer nivel",
@ -227,10 +252,19 @@
"CODE_BLOCK_SAMPLE_TEXT": "Tu texto aquí...", "CODE_BLOCK_SAMPLE_TEXT": "Tu texto aquí...",
"PREVIEW_BUTTON": "Previsualizar", "PREVIEW_BUTTON": "Previsualizar",
"EDIT_BUTTON": "Editar", "EDIT_BUTTON": "Editar",
"ATTACH_FILE_HELP": "Attach files by dragging & dropping on the textarea above.", "ATTACH_FILE_HELP": "Adjunte archivos arrastrando y soltando dentro del area de texto",
"ATTACH_FILE_HELP_SAVE_FIRST": "Si desea guardar adjuntos guarde primero, luego arrastre y suelte los archivos en el area de texto mas arriba",
"MARKDOWN_HELP": "Ayuda de sintaxis Markdown" "MARKDOWN_HELP": "Ayuda de sintaxis Markdown"
}, },
"PERMISIONS_CATEGORIES": { "PERMISIONS_CATEGORIES": {
"EPICS": {
"NAME": "Épicas",
"VIEW_EPICS": "View epics",
"ADD_EPICS": "Add epics",
"MODIFY_EPICS": "Modify epics",
"COMMENT_EPICS": "Comment epics",
"DELETE_EPICS": "Delete epics"
},
"SPRINTS": { "SPRINTS": {
"NAME": "Sprints", "NAME": "Sprints",
"VIEW_SPRINTS": "Ver sprints", "VIEW_SPRINTS": "Ver sprints",
@ -243,6 +277,7 @@
"VIEW_USER_STORIES": "Ver historias de usuario", "VIEW_USER_STORIES": "Ver historias de usuario",
"ADD_USER_STORIES": "Crear historias de usuario", "ADD_USER_STORIES": "Crear historias de usuario",
"MODIFY_USER_STORIES": "Editar historias de usuario", "MODIFY_USER_STORIES": "Editar historias de usuario",
"COMMENT_USER_STORIES": "Comentar historias de usuario",
"DELETE_USER_STORIES": "Borrar historias de usuario" "DELETE_USER_STORIES": "Borrar historias de usuario"
}, },
"TASKS": { "TASKS": {
@ -250,6 +285,7 @@
"VIEW_TASKS": "Ver tareas", "VIEW_TASKS": "Ver tareas",
"ADD_TASKS": "Crear tareas", "ADD_TASKS": "Crear tareas",
"MODIFY_TASKS": "Editar tareas", "MODIFY_TASKS": "Editar tareas",
"COMMENT_TASKS": "Comentar tareas",
"DELETE_TASKS": "Borrar tareas" "DELETE_TASKS": "Borrar tareas"
}, },
"ISSUES": { "ISSUES": {
@ -257,6 +293,7 @@
"VIEW_ISSUES": "Ver peticiones", "VIEW_ISSUES": "Ver peticiones",
"ADD_ISSUES": "Crear peticiones", "ADD_ISSUES": "Crear peticiones",
"MODIFY_ISSUES": "Editar peticiones", "MODIFY_ISSUES": "Editar peticiones",
"COMMENT_ISSUES": "Comentar problemas",
"DELETE_ISSUES": "Borrar peticiones" "DELETE_ISSUES": "Borrar peticiones"
}, },
"WIKI": { "WIKI": {
@ -322,8 +359,8 @@
"PLACEHOLDER_FIELD": "Nombre de usuario o email", "PLACEHOLDER_FIELD": "Nombre de usuario o email",
"ACTION_RESET_PASSWORD": "Restablecer Contraseña", "ACTION_RESET_PASSWORD": "Restablecer Contraseña",
"LINK_CANCEL": "Nah, llévame de vuelta, creo que lo recordé.", "LINK_CANCEL": "Nah, llévame de vuelta, creo que lo recordé.",
"SUCCESS_TITLE": "Check your inbox!", "SUCCESS_TITLE": "¡Revisa tu bandeja de entrada!",
"SUCCESS_TEXT": "We sent you an email with the instructions to set a new password", "SUCCESS_TEXT": "Te hemos enviado un correo con las instrucciones para restablecer tu contraseña",
"ERROR": "Según nuestros Oompa Loompas tú no estás registrado" "ERROR": "Según nuestros Oompa Loompas tú no estás registrado"
}, },
"CHANGE_PASSWORD": { "CHANGE_PASSWORD": {
@ -359,13 +396,48 @@
"HOME": { "HOME": {
"PAGE_TITLE": "Inicio - Taiga", "PAGE_TITLE": "Inicio - Taiga",
"PAGE_DESCRIPTION": "Página de inicio de Taiga, con tus proyectos principales y tus historias de usuario, tareas y peticiones en progreso asignadas y las que observas.", "PAGE_DESCRIPTION": "Página de inicio de Taiga, con tus proyectos principales y tus historias de usuario, tareas y peticiones en progreso asignadas y las que observas.",
"EMPTY_WORKING_ON": "<strong>It feels empty, doesn't it?</strong> Start working with Taiga and you'll see here the stories, tasks and issues you are working on.", "EMPTY_WORKING_ON": "<strong>Parece vacío, ¿no?</strong> Empieza a trabajar con Taiga y verás aquí las historias, tareas e incidentes en los que estás trabajando.",
"EMPTY_WATCHING": "<strong>Sigue</strong> Historias de Usuario, Tareas y Peticiones en tus proyectos y se te notificará sobre sus cambios :)", "EMPTY_WATCHING": "<strong>Sigue</strong> Historias de Usuario, Tareas y Peticiones en tus proyectos y se te notificará sobre sus cambios :)",
"EMPTY_PROJECT_LIST": "Todavía no tienes ningún proyecto", "EMPTY_PROJECT_LIST": "Todavía no tienes ningún proyecto",
"WORKING_ON_SECTION": "Trabajando en", "WORKING_ON_SECTION": "Trabajando en",
"WATCHING_SECTION": "Observando", "WATCHING_SECTION": "Observando",
"DASHBOARD": "Dashboard de proyecto" "DASHBOARD": "Dashboard de proyecto"
}, },
"EPICS": {
"TITLE": "ÉPICAS",
"SECTION_NAME": "Épicas",
"EPIC": "Épica",
"PAGE_TITLE": "Épicas - {{projectName}}",
"PAGE_DESCRIPTION": "El listado de épicas del proyecto {{projectName}}: {{projectDescription}}",
"DASHBOARD": {
"ADD": "+ AÑADIR ÉPICA",
"UNASSIGNED": "No asignado"
},
"EMPTY": {
"TITLE": "Parece que todavía no hay épicas.",
"EXPLANATION": "Epics are items at a higher level that encompass user stories.<br />Epics are at the top of the hierarchy and can be used to group user stories together.",
"HELP": "Aprende más sobre Épicas"
},
"TABLE": {
"VOTES": "Votos",
"NAME": "Nombre",
"PROJECT": "Proyecto",
"SPRINT": "Sprint",
"ASSIGNED_TO": "Assigned",
"STATUS": "Estado",
"PROGRESS": "Progress",
"VIEW_OPTIONS": "View options"
},
"CREATE": {
"TITLE": "Nueva Épica",
"PLACEHOLDER_DESCRIPTION": "Please add descriptive text to help others better understand this epic",
"TEAM_REQUIREMENT": "Team requirement",
"CLIENT_REQUIREMENT": "Client requirement",
"BLOCKED": "Bloqueada",
"BLOCKED_NOTE_PLACEHOLDER": "Why is this epic blocked?",
"CREATE_EPIC": "Create epic"
}
},
"PROJECTS": { "PROJECTS": {
"PAGE_TITLE": "Mis proyectos - Taiga", "PAGE_TITLE": "Mis proyectos - Taiga",
"PAGE_DESCRIPTION": "Una lista con todos tus proyectos, puedes reordenarla o crear un proyecto nuevo.", "PAGE_DESCRIPTION": "Una lista con todos tus proyectos, puedes reordenarla o crear un proyecto nuevo.",
@ -402,7 +474,8 @@
"ADMIN": { "ADMIN": {
"COMMON": { "COMMON": {
"TITLE_ACTION_EDIT_VALUE": "Editar valor", "TITLE_ACTION_EDIT_VALUE": "Editar valor",
"TITLE_ACTION_DELETE_VALUE": "Eliminar valor" "TITLE_ACTION_DELETE_VALUE": "Eliminar valor",
"TITLE_ACTION_DELETE_TAG": "Borrar etiqueta"
}, },
"HELP": "¿Necesitas ayuda? ¡Revisa nuestra pagina de soporte! ", "HELP": "¿Necesitas ayuda? ¡Revisa nuestra pagina de soporte! ",
"PROJECT_DEFAULT_VALUES": { "PROJECT_DEFAULT_VALUES": {
@ -414,8 +487,8 @@
"PAGE_TITLE": "Miembros - {{projectName}}", "PAGE_TITLE": "Miembros - {{projectName}}",
"ADD_BUTTON": "+ Nuevo miembro", "ADD_BUTTON": "+ Nuevo miembro",
"ADD_BUTTON_TITLE": "Añadir un nuevo miembro", "ADD_BUTTON_TITLE": "Añadir un nuevo miembro",
"LIMIT_USERS_WARNING_MESSAGE_FOR_ADMIN": "Unfortunately, this project has reached its limit of <strong>({{members}})</strong> allowed members.", "LIMIT_USERS_WARNING_MESSAGE_FOR_ADMIN": "Desafortunadamente, este proyecto ha alcanzado su límite de <strong>({{members}})</strong> miembros permitidos.",
"LIMIT_USERS_WARNING_MESSAGE_FOR_OWNER": "This project has reached its limit of <strong>({{members}})</strong> allowed members. If you would like to increase that limit please contact the administrator." "LIMIT_USERS_WARNING_MESSAGE_FOR_OWNER": "Este proyecto ha llegado a su límite de <strong>({{members}})</strong> miembros permitidos. Si se desea aumentar ese límite póngase en contacto con el administrador."
}, },
"PROJECT_EXPORT": { "PROJECT_EXPORT": {
"TITLE": "Exportar", "TITLE": "Exportar",
@ -435,12 +508,14 @@
"TITLE": "Módulos", "TITLE": "Módulos",
"ENABLE": "Activado", "ENABLE": "Activado",
"DISABLE": "Desactivado", "DISABLE": "Desactivado",
"EPICS": "Épicas",
"EPICS_DESCRIPTION": "Visualize and manage the most strategic part of your project",
"BACKLOG": "Backlog", "BACKLOG": "Backlog",
"BACKLOG_DESCRIPTION": "Gestiona tus historias de usuario para mantener una vista organizada y priorizada de los próximos trabajos que deberás afrontar. ", "BACKLOG_DESCRIPTION": "Gestiona tus historias de usuario para mantener una vista organizada y priorizada de los próximos trabajos que deberás afrontar. ",
"NUMBER_SPRINTS": "Expected number of sprints", "NUMBER_SPRINTS": "Numero esperado de sprints",
"NUMBER_SPRINTS_HELP": "0 for an undetermined number", "NUMBER_SPRINTS_HELP": "0 para un numero indeterminado",
"NUMBER_US_POINTS": "Expected total of story points", "NUMBER_US_POINTS": "Total esperado de puntos historicos",
"NUMBER_US_POINTS_HELP": "0 for an undetermined number", "NUMBER_US_POINTS_HELP": "0 para un numero indeterminado",
"KANBAN": "Kanban", "KANBAN": "Kanban",
"KANBAN_DESCRIPTION": "Organiza tus proyectos de una manera flexible con este panel.", "KANBAN_DESCRIPTION": "Organiza tus proyectos de una manera flexible con este panel.",
"ISSUES": "Peticiones", "ISSUES": "Peticiones",
@ -448,9 +523,9 @@
"WIKI": "Wiki", "WIKI": "Wiki",
"WIKI_DESCRIPTION": "Añade, modifica o borra contenido en colaboración con otros miembros. Este es el lugar adecuado para la documentación de tu proyecto.", "WIKI_DESCRIPTION": "Añade, modifica o borra contenido en colaboración con otros miembros. Este es el lugar adecuado para la documentación de tu proyecto.",
"MEETUP": "Meet Up", "MEETUP": "Meet Up",
"MEETUP_DESCRIPTION": "Choose your videoconference system.", "MEETUP_DESCRIPTION": "Elegir su sistema de videoconferencia.",
"SELECT_VIDEOCONFERENCE": "Elige un sistema de videoconferencia", "SELECT_VIDEOCONFERENCE": "Elige un sistema de videoconferencia",
"SALT_CHAT_ROOM": "Add a prefix to the chatroom name", "SALT_CHAT_ROOM": "Agregar prefijo al nombre de la sala de chat",
"JITSI_CHAT_ROOM": "Jitsi", "JITSI_CHAT_ROOM": "Jitsi",
"APPEARIN_CHAT_ROOM": "AppearIn", "APPEARIN_CHAT_ROOM": "AppearIn",
"TALKY_CHAT_ROOM": "Talky", "TALKY_CHAT_ROOM": "Talky",
@ -474,19 +549,19 @@
"LOGO_HELP": "La imagen se escalará a 80x80px.", "LOGO_HELP": "La imagen se escalará a 80x80px.",
"CHANGE_LOGO": "Cambia el logo", "CHANGE_LOGO": "Cambia el logo",
"ACTION_USE_DEFAULT_LOGO": "Usar imagen por defecto", "ACTION_USE_DEFAULT_LOGO": "Usar imagen por defecto",
"MAX_PRIVATE_PROJECTS": "You've reached the maximum number of private projects allowed by your current plan", "MAX_PRIVATE_PROJECTS": "Has alcanzado el número máximo de proyectos privados permitidos por su actual plan",
"MAX_PRIVATE_PROJECTS_MEMBERS": "The maximum number of members for private projects has been exceeded", "MAX_PRIVATE_PROJECTS_MEMBERS": "El numero máximo de miembros para proyectos privados se ha excedido",
"MAX_PUBLIC_PROJECTS": "Unfortunately, you've reached the maximum number of public projects allowed by your current plan", "MAX_PUBLIC_PROJECTS": "Desafortunadamente, usted ha alcanzado el número máximo de proyectos públicos permitidos por su plan actual",
"MAX_PUBLIC_PROJECTS_MEMBERS": "The project exceeds your maximum number of members for public projects", "MAX_PUBLIC_PROJECTS_MEMBERS": "El proyecto excede el numero maximo de usuarios para proyectos publicos",
"PROJECT_OWNER": "Project owner", "PROJECT_OWNER": "Dueño del proyecto",
"REQUEST_OWNERSHIP": "Request ownership", "REQUEST_OWNERSHIP": "Solicitar de dueño",
"REQUEST_OWNERSHIP_CONFIRMATION_TITLE": "Do you want to become the new project owner?", "REQUEST_OWNERSHIP_CONFIRMATION_TITLE": "¿Desea convertirse en el nuevo dueño del proyecto?",
"REQUEST_OWNERSHIP_DESC": "Request that current project owner {{name}} transfer ownership of this project to you.", "REQUEST_OWNERSHIP_DESC": "Solicitar que el actual project owner {{name}} te transfiera la propiedad de este proyecto a ti.",
"REQUEST_OWNERSHIP_BUTTON": "Solicitud", "REQUEST_OWNERSHIP_BUTTON": "Solicitud",
"REQUEST_OWNERSHIP_SUCCESS": "We'll notify the project owner", "REQUEST_OWNERSHIP_SUCCESS": "Notificaremos al dueño del proyecto",
"CHANGE_OWNER": "Change owner", "CHANGE_OWNER": "Cambiar dueño",
"CHANGE_OWNER_SUCCESS_TITLE": "Ok, your request has been sent!", "CHANGE_OWNER_SUCCESS_TITLE": "Ok, su solicitud ha sido enviado!",
"CHANGE_OWNER_SUCCESS_DESC": "We will notify you by email if the project ownership request is accepted or declined" "CHANGE_OWNER_SUCCESS_DESC": "Le notificaremos por correo si la solicitud para ser dueño del proyecto fue aceptada o rechazada"
}, },
"REPORTS": { "REPORTS": {
"TITLE": "Informes", "TITLE": "Informes",
@ -497,6 +572,7 @@
"REGENERATE_SUBTITLE": "Vas a cambiar la url de acceso a los datos en formato CSV. La url anterior se deshabilitará. ¿Estás seguro?" "REGENERATE_SUBTITLE": "Vas a cambiar la url de acceso a los datos en formato CSV. La url anterior se deshabilitará. ¿Estás seguro?"
}, },
"CSV": { "CSV": {
"SECTION_TITLE_EPIC": "epics reports",
"SECTION_TITLE_US": "informes de historias de usuario", "SECTION_TITLE_US": "informes de historias de usuario",
"SECTION_TITLE_TASK": "Informes de tareas", "SECTION_TITLE_TASK": "Informes de tareas",
"SECTION_TITLE_ISSUE": "informes de peticiones", "SECTION_TITLE_ISSUE": "informes de peticiones",
@ -509,6 +585,8 @@
"CUSTOM_FIELDS": { "CUSTOM_FIELDS": {
"TITLE": "Atributos personalizados", "TITLE": "Atributos personalizados",
"SUBTITLE": "Especifica los atributos personalizados para las historias de usuario, tareas y peticiones", "SUBTITLE": "Especifica los atributos personalizados para las historias de usuario, tareas y peticiones",
"EPIC_DESCRIPTION": "Epics custom fields",
"EPIC_ADD": "Add a custom field in epics",
"US_DESCRIPTION": "Atributos personalizados de historias de usuario", "US_DESCRIPTION": "Atributos personalizados de historias de usuario",
"US_ADD": "Añadir un atributo personalizado en las historias de usuario", "US_ADD": "Añadir un atributo personalizado en las historias de usuario",
"TASK_DESCRIPTION": "Atributos personalizados de tareas", "TASK_DESCRIPTION": "Atributos personalizados de tareas",
@ -546,7 +624,8 @@
"PROJECT_VALUES_STATUS": { "PROJECT_VALUES_STATUS": {
"TITLE": "Estado", "TITLE": "Estado",
"SUBTITLE": "Especifica los estado que atravesarán tus historias de usuario, tareas y peticiones", "SUBTITLE": "Especifica los estado que atravesarán tus historias de usuario, tareas y peticiones",
"US_TITLE": "Estados de historias", "EPIC_TITLE": "Epic Statuses",
"US_TITLE": "User Story Statuses",
"TASK_TITLE": "Estados de Tarea", "TASK_TITLE": "Estados de Tarea",
"ISSUE_TITLE": "Estados de la petición" "ISSUE_TITLE": "Estados de la petición"
}, },
@ -556,6 +635,17 @@
"ISSUE_TITLE": "Tipos de la petición", "ISSUE_TITLE": "Tipos de la petición",
"ACTION_ADD": "Añadir nuevo {{objName}}" "ACTION_ADD": "Añadir nuevo {{objName}}"
}, },
"PROJECT_VALUES_TAGS": {
"TITLE": "Etiquetas",
"SUBTITLE": "View and edit the color of your tags",
"EMPTY": "Actualmente no hay etiquetas",
"EMPTY_SEARCH": "Parece que no se encontro nada con este criterio de busqueda",
"ACTION_ADD": "Añadir etiqueta",
"NEW_TAG": "New tag",
"MIXING_HELP_TEXT": "Select the tags that you want to merge",
"MIXING_MERGE": "Merge Tags",
"SELECTED": "Selected"
},
"ROLES": { "ROLES": {
"PAGE_TITLE": "Roles - {{projectName}}", "PAGE_TITLE": "Roles - {{projectName}}",
"WARNING_NO_ROLE": "Ojo, ningún rol en tu proyecto podrá estimar historias de usuario", "WARNING_NO_ROLE": "Ojo, ningún rol en tu proyecto podrá estimar historias de usuario",
@ -565,7 +655,7 @@
"COUNT_MEMBERS": "{{ role.members_count }} miembros con este rol", "COUNT_MEMBERS": "{{ role.members_count }} miembros con este rol",
"TITLE_DELETE_ROLE": "Borrar Rol", "TITLE_DELETE_ROLE": "Borrar Rol",
"REPLACEMENT_ROLE": "Todos los usuarios con este rol serán movidos a", "REPLACEMENT_ROLE": "Todos los usuarios con este rol serán movidos a",
"WARNING_DELETE_ROLE": "Be careful! All role estimations will be removed", "WARNING_DELETE_ROLE": "¡Ten cuidado! Todas las estimaciones de roles serán eliminados",
"ERROR_DELETE_ALL": "No puedes eliminar todos los valores", "ERROR_DELETE_ALL": "No puedes eliminar todos los valores",
"EXTERNAL_USER": "Usuario externo" "EXTERNAL_USER": "Usuario externo"
}, },
@ -588,6 +678,10 @@
"SECTION_NAME": "Github", "SECTION_NAME": "Github",
"PAGE_TITLE": "Github - {{projectName}}" "PAGE_TITLE": "Github - {{projectName}}"
}, },
"GOGS": {
"SECTION_NAME": "Gogs",
"PAGE_TITLE": "Gogs - {{projectName}}"
},
"WEBHOOKS": { "WEBHOOKS": {
"PAGE_TITLE": "Webhooks - {{projectName}}", "PAGE_TITLE": "Webhooks - {{projectName}}",
"SECTION_NAME": "Webhooks", "SECTION_NAME": "Webhooks",
@ -643,13 +737,14 @@
"DEFAULT_DELETE_MESSAGE": "la invitación enviada a" "DEFAULT_DELETE_MESSAGE": "la invitación enviada a"
}, },
"DEFAULT_VALUES": { "DEFAULT_VALUES": {
"LABEL_EPIC_STATUS": "Default value for epic status selector",
"LABEL_US_STATUS": "Default value for user story status selector",
"LABEL_POINTS": "Valor por defecto para el selector de puntos", "LABEL_POINTS": "Valor por defecto para el selector de puntos",
"LABEL_US": "Valor por defecto para el selector de estado de historia",
"LABEL_TASK_STATUS": "Valor por defecto para el selector de estado de tarea", "LABEL_TASK_STATUS": "Valor por defecto para el selector de estado de tarea",
"LABEL_PRIORITY": "Valor por defecto para el selector de prioridad",
"LABEL_SEVERITY": "Valor por defecto para el selector de gravedad",
"LABEL_ISSUE_TYPE": "Valor por defecto para el selector de tipo de la petición", "LABEL_ISSUE_TYPE": "Valor por defecto para el selector de tipo de la petición",
"LABEL_ISSUE_STATUS": "Valor por defecto para el selector de estado de petición" "LABEL_ISSUE_STATUS": "Valor por defecto para el selector de estado de petición",
"LABEL_PRIORITY": "Valor por defecto para el selector de prioridad",
"LABEL_SEVERITY": "Valor por defecto para el selector de gravedad"
}, },
"STATUS": { "STATUS": {
"PLACEHOLDER_WRITE_STATUS_NAME": "Escribe un nombre para el nuevo estado" "PLACEHOLDER_WRITE_STATUS_NAME": "Escribe un nombre para el nuevo estado"
@ -681,7 +776,8 @@
"PRIORITIES": "Prioridades", "PRIORITIES": "Prioridades",
"SEVERITIES": "Gravedades", "SEVERITIES": "Gravedades",
"TYPES": "Tipos", "TYPES": "Tipos",
"CUSTOM_FIELDS": "Atributos personalizados" "CUSTOM_FIELDS": "Atributos personalizados",
"TAGS": "Etiquetas"
}, },
"SUBMENU_PROJECT_PROFILE": { "SUBMENU_PROJECT_PROFILE": {
"TITLE": "Perfil de proyecto" "TITLE": "Perfil de proyecto"
@ -695,21 +791,21 @@
"TITLE": "Servicios" "TITLE": "Servicios"
}, },
"PROJECT_TRANSFER": { "PROJECT_TRANSFER": {
"DO_YOU_ACCEPT_PROJECT_OWNERNSHIP": "Would you like to become the new project owner?", "DO_YOU_ACCEPT_PROJECT_OWNERNSHIP": "¿Te gustaría ser el nuevo project owner?",
"PRIVATE": "Private", "PRIVATE": "Privado",
"ACCEPTED_PROJECT_OWNERNSHIP": "Congratulations! You're now the new project owner.", "ACCEPTED_PROJECT_OWNERNSHIP": "¡Felicitaciones! Usted es ahora el nuevo propietario del proyecto.",
"REJECTED_PROJECT_OWNERNSHIP": "OK. We'll contact the current project owner", "REJECTED_PROJECT_OWNERNSHIP": "Ok. Nos pondremos en contacto con el propietario actual del proyecto",
"ACCEPT": "Aceptar", "ACCEPT": "Aceptar",
"REJECT": "Reject", "REJECT": "Rechazar",
"PROPOSE_OWNERSHIP": "<strong>{{owner}}</strong>, the current owner of the project <strong>{{project}}</strong> has asked that you become the new project owner.", "PROPOSE_OWNERSHIP": "<strong>{{owner}}</strong>, el dueño del proyecto <strong>{{project}}</strong> pregunta si es el nuevo dueño del proyecto.",
"ADD_COMMENT": "Would you like to add a comment for the project owner?", "ADD_COMMENT": "¿Te gustaría añadir un comentario para el project owner?",
"UNLIMITED_PROJECTS": "Unlimited", "UNLIMITED_PROJECTS": "Sin límite",
"OWNER_MESSAGE": { "OWNER_MESSAGE": {
"PRIVATE": "Please remember that you can own up to <strong>{{maxProjects}}</strong> private projects. You currently own <strong>{{currentProjects}}</strong> private projects", "PRIVATE": "Por favor recuerde que puede ser dueño de maximo <strong>{{maxProjects}}</strong> proyectos privados. Usted tiene actualmente <strong>{{currentProjects}}</strong> proyectos privados bajo su poder",
"PUBLIC": "Please remember that you can own up to <strong>{{maxProjects}}</strong> public projects. You currently own <strong>{{currentProjects}}</strong> public projects" "PUBLIC": "Pro favor recuerde que solo puede ser dueño de maximo <strong>{{maxProjects}}</strong> proyectos publicos. Actualmente tiene <strong>{{currentProjects}}</strong> proyectos publicos bajo su poder"
}, },
"CANT_BE_OWNED": "At the moment you cannot become an owner of a project of this type. If you would like to become the owner of this project, please contact the administrator so they change your account settings to enable project ownership.", "CANT_BE_OWNED": "en el momento no puede ser el dueño de un proyecto de este tipo. Si desea ser el dueño de este proyecto, por favor contacte al administrador para cambiar la configuracion que le permita ser dueño del proyecto",
"CHANGE_MY_PLAN": "Change my plan" "CHANGE_MY_PLAN": "Cambiar mi plan"
} }
}, },
"USER": { "USER": {
@ -751,6 +847,8 @@
"FILTER_TYPE_ALL_TITLE": "Mostrar todos", "FILTER_TYPE_ALL_TITLE": "Mostrar todos",
"FILTER_TYPE_PROJECTS": "Proyectos", "FILTER_TYPE_PROJECTS": "Proyectos",
"FILTER_TYPE_PROJECT_TITLES": "Mostrar sólo proyectos", "FILTER_TYPE_PROJECT_TITLES": "Mostrar sólo proyectos",
"FILTER_TYPE_EPICS": "Épicas",
"FILTER_TYPE_EPIC_TITLES": "Show only epics",
"FILTER_TYPE_USER_STORIES": "Historias", "FILTER_TYPE_USER_STORIES": "Historias",
"FILTER_TYPE_USER_STORIES_TITLES": "Mostrar sólo historias de usuario", "FILTER_TYPE_USER_STORIES_TITLES": "Mostrar sólo historias de usuario",
"FILTER_TYPE_TASKS": "Tareas", "FILTER_TYPE_TASKS": "Tareas",
@ -771,9 +869,9 @@
"WATCHERS_COUNTER_TITLE": "{total, plural, one{un observador} other{# observadores}}", "WATCHERS_COUNTER_TITLE": "{total, plural, one{un observador} other{# observadores}}",
"MEMBERS_COUNTER_TITLE": "{total, plural, one{un miembro} other{# miembros}}", "MEMBERS_COUNTER_TITLE": "{total, plural, one{un miembro} other{# miembros}}",
"BLOCKED_PROJECT": { "BLOCKED_PROJECT": {
"BLOCKED": "Blocked project", "BLOCKED": "Proyecto bloqueado",
"THIS_PROJECT_IS_BLOCKED": "This project is temporarily blocked", "THIS_PROJECT_IS_BLOCKED": "Este proyecto esta temporalmente bloqueado",
"TO_UNBLOCK_CONTACT_THE_ADMIN_STAFF": "In order to unblock your projects, contact the administrator." "TO_UNBLOCK_CONTACT_THE_ADMIN_STAFF": "Para desbloquear sus proyectos, contacte al administrador."
}, },
"STATS": { "STATS": {
"PROJECT": "puntos<br/> proyecto", "PROJECT": "puntos<br/> proyecto",
@ -838,28 +936,28 @@
"ERROR_MAX_SIZE_EXCEEDED": "El fichero '{{fileName}}' ({{fileSize}}) es demasiado pesado para nuestros Oompa Loompas, prueba con uno de menos de ({{maxFileSize}}).", "ERROR_MAX_SIZE_EXCEEDED": "El fichero '{{fileName}}' ({{fileSize}}) es demasiado pesado para nuestros Oompa Loompas, prueba con uno de menos de ({{maxFileSize}}).",
"SYNC_SUCCESS": "Tu proyecto se ha importado con éxito.", "SYNC_SUCCESS": "Tu proyecto se ha importado con éxito.",
"PROJECT_RESTRICTIONS": { "PROJECT_RESTRICTIONS": {
"PROJECT_MEMBERS_DESC": "The project you are trying to import has {{members}} members, unfortunately, your current plan allows for a maximum of {{max_memberships}} members per project. If you would like to increase that limit please contact the administrator.", "PROJECT_MEMBERS_DESC": "El proyecto que esta tratando de importar tiene {{members}} miembros, desafortunadamente, su plna actual solo le permite un maximo de {{max_memberships}} miembros por proyecto. si desea aumentar este limite por favor contacte al administrador.",
"PRIVATE_PROJECTS_SPACE": { "PRIVATE_PROJECTS_SPACE": {
"TITLE": "Unfortunately, your current plan does not allow for additional private projects", "TITLE": "Desafortunadamente, su plan actual no permite a los proyectos privados adicionales",
"DESC": "The project you are trying to import is private. Unfortunately, your current plan does not allow for additional private projects." "DESC": "El proyecto que trata de importar es privado. Desafortunadamente, su plan actual no le permite adicionar mas proyectos privados"
}, },
"PUBLIC_PROJECTS_SPACE": { "PUBLIC_PROJECTS_SPACE": {
"TITLE": "Unfortunately, your current plan does not allow for additional public projects", "TITLE": "Desafortunadamente, su plan actual no permite adicionar mas proyectos publicos",
"DESC": "The project you are trying to import is public. Unfortunately, your current plan does not allow additional public projects." "DESC": "El proyecto que estás intento importar es público. Desafortunadamente, tu plan actual no permite proyectos públicos adicionales."
}, },
"PRIVATE_PROJECTS_MEMBERS": { "PRIVATE_PROJECTS_MEMBERS": {
"TITLE": "Your current plan allows for a maximum of {{max_memberships}} members per private project" "TITLE": "Su plan actual solo permite un numero maximo de {{max_memberships}} miembros por proyecto privado"
}, },
"PUBLIC_PROJECTS_MEMBERS": { "PUBLIC_PROJECTS_MEMBERS": {
"TITLE": "Your current plan allows for a maximum of {{max_memberships}} members per public project." "TITLE": "Su plan actual solo permite un maximo de {{max_memberships}} miembros por proyecto publico."
}, },
"PRIVATE_PROJECTS_SPACE_MEMBERS": { "PRIVATE_PROJECTS_SPACE_MEMBERS": {
"TITLE": "Unfortunately your current plan doesn't allow additional private projects or an increase of more than {{max_memberships}} members per private project", "TITLE": "Desafortunadamente tu plan actual no permite proyectos privados adicionales o un incremento de más de {{max_memberships}} miembros por proyecto privado",
"DESC": "The project that you are trying to import is private and has {{members}} members." "DESC": "El proyecto que estás intentando importar es privado y tiene {{members}} miembros."
}, },
"PUBLIC_PROJECTS_SPACE_MEMBERS": { "PUBLIC_PROJECTS_SPACE_MEMBERS": {
"TITLE": "Unfortunately your current plan doesn't allow additional public projects or an increase of more than {{max_memberships}} members per public project", "TITLE": "Desafortunadamente su plan actual no le permite adicionar proyectos publicos o un aumento de {{max_memberships}} miembros por proyecto publico",
"DESC": "The project that you are trying to import is public and has more than {{members}} members." "DESC": "El proyecto que estás intentando importar es público y tiene más de {{members}} miembros."
} }
} }
}, },
@ -890,10 +988,10 @@
"SECTION_NAME": "Eliminar cuenta de Taiga", "SECTION_NAME": "Eliminar cuenta de Taiga",
"CONFIRM": "¿Está seguro que deseas eliminar tu cuenta de Taiga?", "CONFIRM": "¿Está seguro que deseas eliminar tu cuenta de Taiga?",
"NEWSLETTER_LABEL_TEXT": "No quiero recibir la newsletter nunca más.", "NEWSLETTER_LABEL_TEXT": "No quiero recibir la newsletter nunca más.",
"CANCEL": "Back to settings", "CANCEL": "Volver a los ajustes",
"ACCEPT": "Delete account", "ACCEPT": "Eliminar cuenta",
"BLOCK_PROJECT": "Note that all the projects you own projects will be <strong>blocked</strong> after you delete your account. If you do want a project blocked, transfer ownership to another member of each project prior to deleting your account.", "BLOCK_PROJECT": "Recuerde que todos los proyectos de los cuales usted es dueño seran <strong>bloqueados</strong> despues de eliminar su cuenta. si desea mantener un proyecto bloqueado, transfiera el dominio a otro usuario en cada proyecto antes de eliminar la cuenta.",
"SUBTITLE": "Sorry to see you go. We'll be here if you should ever consider us again! :(" "SUBTITLE": "Sentimos mucho verte ir. Estaremos aquí por si alguna vez nos consideras de nuevo! :("
}, },
"DELETE_PROJECT": { "DELETE_PROJECT": {
"TITLE": "Borrar proyecto", "TITLE": "Borrar proyecto",
@ -950,30 +1048,50 @@
"CREATE_MEMBER": { "CREATE_MEMBER": {
"PLACEHOLDER_INVITATION_TEXT": "(Opcional) Añade un texto personalizado a la invitación. Dile algo encantador a tus nuevos miembros ;-)", "PLACEHOLDER_INVITATION_TEXT": "(Opcional) Añade un texto personalizado a la invitación. Dile algo encantador a tus nuevos miembros ;-)",
"PLACEHOLDER_TYPE_EMAIL": "Escribe un email", "PLACEHOLDER_TYPE_EMAIL": "Escribe un email",
"LIMIT_USERS_WARNING_MESSAGE_FOR_OWNER": "Unfortunately, this project can't have more than <strong>{{maxMembers}}</strong> members.<br> If you would like to increase the current limit, please contact the administrator.", "LIMIT_USERS_WARNING_MESSAGE_FOR_OWNER": "You are about to reach the maximum number of members allowed for this project, <strong>{{maxMembers}}</strong> members. If you would like to increase the current limit, please contact the administrator.",
"LIMIT_USERS_WARNING_MESSAGE": "Unfortunately, this project can't have more than <strong>{{maxMembers}}</strong> members." "LIMIT_USERS_WARNING_MESSAGE": "You are about to reach the maximum number of members allowed for this project, <strong>{{maxMembers}}</strong> members."
}, },
"LEAVE_PROJECT_WARNING": { "LEAVE_PROJECT_WARNING": {
"TITLE": "Unfortunately, this project can't be left without an owner", "TITLE": "Por desgracia, este proyecto no puede ser dejado sin dueño",
"CURRENT_USER_OWNER": { "CURRENT_USER_OWNER": {
"DESC": "You are the current owner of this project. Before leaving, please transfer ownership to someone else.", "DESC": "Usted es el dueño actual de este proyecto. Antes de salir, tranfiera el dominio de su proyecto a alguien mas.",
"BUTTON": "Change the project owner" "BUTTON": "Cambiar el dueño del proyecto"
}, },
"OTHER_USER_OWNER": { "OTHER_USER_OWNER": {
"DESC": "Unfortunately, you can't delete a member who is also the current project owner. First, please assign a new project owner.", "DESC": "Desafortunadamente, usted no puede eliminar un miembro que es a su vez el dueño actual del proyecto. Primero, por favor asigne un nuevo dueño del proyecto.",
"BUTTON": "Request project owner change" "BUTTON": "Solicitud del cambio del dueño del proyecto"
} }
}, },
"CHANGE_OWNER": { "CHANGE_OWNER": {
"TITLE": "Who do you want to be the new project owner?", "TITLE": "¿A quién quiere ser el nuevo dueño del proyecto?",
"ADD_COMMENT": "Add comment", "ADD_COMMENT": "Añadir comentario",
"BUTTON": "Ask this project member to become the new project owner" "BUTTON": "Pregunte a este usuario para convertirlo en el nuero dueño del proyecto"
} }
}, },
"EPIC": {
"PAGE_TITLE": "{{epicSubject}} - Épica {{epicRef}} - {{projectName}}",
"PAGE_DESCRIPTION": "Status: {{epicStatus }}. Description: {{epicDescription}}",
"SECTION_NAME": "Epic",
"TITLE_LIGHTBOX_UNLINK_RELATED_USERSTORY": "Unlink related userstory",
"MSG_LIGHTBOX_UNLINK_RELATED_USERSTORY": "It will delete the link to the related userstory '{{subject}}'",
"ERROR_UNLINK_RELATED_USERSTORY": "We have not been able to unlink: {{errorMessage}}",
"CREATE_RELATED_USERSTORIES": "Create a relationship with",
"NEW_USERSTORY": "Nueva historia de usuario",
"EXISTING_USERSTORY": "Existing user story",
"CHOOSE_PROJECT_FOR_CREATION": "What's the project?",
"SUBJECT": "Asunto",
"SUBJECT_BULK_MODE": "Subject (bulk insert)",
"CHOOSE_PROJECT_FROM": "What's the project?",
"CHOOSE_USERSTORY": "What's the user story?",
"NO_USERSTORIES": "This project has no User Stories yet. Please select another project.",
"FILTER_USERSTORIES": "Filter user stories",
"LIGHTBOX_TITLE_BLOKING_EPIC": "Blocking epic",
"ACTION_DELETE": "Delete epic"
},
"US": { "US": {
"PAGE_TITLE": "{{userStorySubject}} - Historia de Usuario {{userStoryRef}} - {{projectName}}", "PAGE_TITLE": "{{userStorySubject}} - Historia de Usuario {{userStoryRef}} - {{projectName}}",
"PAGE_DESCRIPTION": "Estado: {{userStoryStatus }}. Completado el {{userStoryProgressPercentage}}% ({{userStoryClosedTasks}} de {{userStoryTotalTasks}} tareas cerradas). Puntos: {{userStoryPoints}}. Descripción: {{userStoryDescription}}", "PAGE_DESCRIPTION": "Estado: {{userStoryStatus }}. Completado el {{userStoryProgressPercentage}}% ({{userStoryClosedTasks}} de {{userStoryTotalTasks}} tareas cerradas). Puntos: {{userStoryPoints}}. Descripción: {{userStoryDescription}}",
"SECTION_NAME": "Detalles de historia de usuario", "SECTION_NAME": "Historia de usuario",
"LINK_TASKBOARD": "Panel de tareas", "LINK_TASKBOARD": "Panel de tareas",
"TITLE_LINK_TASKBOARD": "Ir al panel de tareas", "TITLE_LINK_TASKBOARD": "Ir al panel de tareas",
"TOTAL_POINTS": "puntos totales", "TOTAL_POINTS": "puntos totales",
@ -984,14 +1102,23 @@
"EXTERNAL_REFERENCE": "Esta historia ha sido creada desde", "EXTERNAL_REFERENCE": "Esta historia ha sido creada desde",
"GO_TO_EXTERNAL_REFERENCE": "Ir al origen", "GO_TO_EXTERNAL_REFERENCE": "Ir al origen",
"BLOCKED": "Esta historia de usuario está bloqueada", "BLOCKED": "Esta historia de usuario está bloqueada",
"PREVIOUS": "anterior historia de usuario",
"NEXT": "siguiente historia de usuario",
"TITLE_DELETE_ACTION": "Borrar Historia de Usuario", "TITLE_DELETE_ACTION": "Borrar Historia de Usuario",
"LIGHTBOX_TITLE_BLOKING_US": "Historia bloqueada", "LIGHTBOX_TITLE_BLOKING_US": "Historia bloqueada",
"TASK_COMPLETED": "{{totalClosedTasks}}/{{totalTasks}} tareas completadas", "TASK_COMPLETED": "{{totalClosedTasks}}/{{totalTasks}} tareas completadas",
"ASSIGN": "Asignar Historia de Usuario", "ASSIGN": "Asignar Historia de Usuario",
"NOT_ESTIMATED": "No estimada", "NOT_ESTIMATED": "No estimada",
"TOTAL_US_POINTS": "Total puntos de historia", "TOTAL_US_POINTS": "Total puntos de historia",
"TRIBE": {
"PUBLISH": "Publicar como Gig en la Tribu Taiga",
"PUBLISH_INFO": "Mas información",
"PUBLISH_TITLE": "Mas informacion para publicar en la Tribu Taiga",
"PUBLISHED_AS_GIG": "Historia publicada como Gig en la Tribu Taiga",
"EDIT_LINK": "Editar link",
"CLOSE": "Cerrar",
"SYNCHRONIZE_LINK": "sincronizar con la Tribu Taiga",
"PUBLISH_MORE_INFO_TITLE": "Necesita a alguien para esta tarea?",
"PUBLISH_MORE_INFO_TEXT": "<p>SI necesita ayuda con una parte especifica del trabajo puede crear facilmente gigs en<a href='taigatribe.com' title='Taiga Tribe'> la Tribu Taiga </a> y recibir ayuda de todo el mundo. Tendra la habilidad de manejar y controlar su gig disfrutando de una comunidad dispuesta a colaborar.</p><p><a href='taigatribe.com' title='Tribu Taiga'> la Tribu Taiga </a> nacio como una rama de Taiga. Ambas plataformas viven separadas Pero creemos que hay mucho poder al usarlas combinadamente y asi aseguramos que la integracion funciona muy bien.</p>"
},
"FIELDS": { "FIELDS": {
"TEAM_REQUIREMENT": "Requerido por el Equipo", "TEAM_REQUIREMENT": "Requerido por el Equipo",
"CLIENT_REQUIREMENT": "Requerido por el Cliente", "CLIENT_REQUIREMENT": "Requerido por el Cliente",
@ -999,28 +1126,47 @@
} }
}, },
"COMMENTS": { "COMMENTS": {
"DELETED_INFO": "Comentario borrado por {{user}} el {{date}}", "DELETED_INFO": "Comentario borrado por {{user}}",
"TITLE": "Comentarios", "TITLE": "Comentarios",
"COMMENTS_COUNT": "{{comments}} Comentarios",
"ORDER": "Orden",
"OLDER_FIRST": "Mas antiguo primero",
"RECENT_FIRST": "Mas reciente primero",
"COMMENT": "Comentar", "COMMENT": "Comentar",
"EDIT_COMMENT": "Editar comentario",
"EDITED_COMMENT": "Editado:",
"SHOW_HISTORY": "Ver histórico",
"TYPE_NEW_COMMENT": "Escribe un nuevo comentario aquí", "TYPE_NEW_COMMENT": "Escribe un nuevo comentario aquí",
"SHOW_DELETED": "Mostrar comentarios eliminados", "SHOW_DELETED": "Mostrar comentarios eliminados",
"HIDE_DELETED": "Ocultar comentarios eliminados", "HIDE_DELETED": "Ocultar comentarios eliminados",
"DELETE": "Borrar comentario", "DELETE": "Borrar comentario",
"RESTORE": "Restaurar comentario" "RESTORE": "Restaurar comentario",
"HISTORY": {
"TITLE": "Actividad"
}
}, },
"ACTIVITY": { "ACTIVITY": {
"SHOW_ACTIVITY": "Mostrar actividad", "SHOW_ACTIVITY": "Mostrar actividad",
"DATETIME": "DD MMM YYYY HH:mm", "DATETIME": "DD MMM YYYY HH:mm",
"SHOW_MORE": "+ Ver entradas anteriores ({{showMore}} más)", "SHOW_MORE": "+ Ver entradas anteriores ({{showMore}} más)",
"TITLE": "Actividad", "TITLE": "Actividad",
"ACTIVITIES_COUNT": "{{activities}} Actividades",
"REMOVED": "borrado", "REMOVED": "borrado",
"ADDED": "agregado", "ADDED": "agregado",
"US_POINTS": "Puntos de historia ({{name}})", "TAGS_ADDED": "etiquetas añadidas",
"TAGS_REMOVED": "Etiquetas borradas:",
"US_POINTS": "{{role}} puntos",
"NEW_ATTACHMENT": "nuevo adjunto", "NEW_ATTACHMENT": "nuevo adjunto",
"DELETED_ATTACHMENT": "adjunto eliminado", "DELETED_ATTACHMENT": "adjunto borrado",
"UPDATED_ATTACHMENT": "Adjunto {{filename}} actualizado", "UPDATED_ATTACHMENT": "actualizar adjunto ({{filename}}):",
"DELETED_CUSTOM_ATTRIBUTE": "eliminar atributos personalizados", "CREATED_CUSTOM_ATTRIBUTE": "atributo personalizado creado",
"UPDATED_CUSTOM_ATTRIBUTE": "atributo personalizado actualizado",
"SIZE_CHANGE": "{size, plural, one{Un cambio realizado} other{# cambios realizados}}", "SIZE_CHANGE": "{size, plural, one{Un cambio realizado} other{# cambios realizados}}",
"BECAME_DEPRECATED": "esta obsoleto",
"BECAME_UNDEPRECATED": "no esta obsoleto",
"TEAM_REQUIREMENT": "Requerido por el Equipo",
"CLIENT_REQUIREMENT": "Requerido por el Cliente",
"BLOCKED": "Bloqueada",
"VALUES": { "VALUES": {
"YES": "sí", "YES": "sí",
"NO": "no", "NO": "no",
@ -1052,12 +1198,14 @@
"TAGS": "etiquetas", "TAGS": "etiquetas",
"ATTACHMENTS": "adjuntos", "ATTACHMENTS": "adjuntos",
"IS_DEPRECATED": "está desactualizado", "IS_DEPRECATED": "está desactualizado",
"IS_NOT_DEPRECATED": "No es obsoleto",
"ORDER": "orden", "ORDER": "orden",
"BACKLOG_ORDER": "orden en backlog", "BACKLOG_ORDER": "orden en backlog",
"SPRINT_ORDER": "orden en sprint", "SPRINT_ORDER": "orden en sprint",
"KANBAN_ORDER": "orden en kanban", "KANBAN_ORDER": "orden en kanban",
"TASKBOARD_ORDER": "orden en panel de tareas", "TASKBOARD_ORDER": "orden en panel de tareas",
"US_ORDER": "orden en historia" "US_ORDER": "orden en historia",
"COLOR": "color"
} }
}, },
"BACKLOG": { "BACKLOG": {
@ -1109,7 +1257,8 @@
"CLOSED_TASKS": "tareas<br />cerradas", "CLOSED_TASKS": "tareas<br />cerradas",
"IOCAINE_DOSES": "dosis de<br >iocaína", "IOCAINE_DOSES": "dosis de<br >iocaína",
"SHOW_STATISTICS_TITLE": "Ver estadísticas", "SHOW_STATISTICS_TITLE": "Ver estadísticas",
"TOGGLE_BAKLOG_GRAPH": "Ver/Ocultar gráfica de burndown" "TOGGLE_BAKLOG_GRAPH": "Ver/Ocultar gráfica de burndown",
"POINTS_PER_ROLE": "Points per role"
}, },
"SUMMARY": { "SUMMARY": {
"PROJECT_POINTS": "puntos<br /> proyecto", "PROJECT_POINTS": "puntos<br /> proyecto",
@ -1122,9 +1271,7 @@
"TITLE": "Filtros", "TITLE": "Filtros",
"REMOVE": "Borrar Filtros", "REMOVE": "Borrar Filtros",
"HIDE": "Ocultar filtros", "HIDE": "Ocultar filtros",
"SHOW": "Ver Filtros", "SHOW": "Ver Filtros"
"FILTER_CATEGORY_STATUS": "Estado",
"FILTER_CATEGORY_TAGS": "Etiquetas"
}, },
"SPRINTS": { "SPRINTS": {
"TITLE": "SPRINTS", "TITLE": "SPRINTS",
@ -1179,7 +1326,7 @@
"TASK": { "TASK": {
"PAGE_TITLE": "{{taskSubject}} - Tarea {{taskRef}} - {{projectName}}", "PAGE_TITLE": "{{taskSubject}} - Tarea {{taskRef}} - {{projectName}}",
"PAGE_DESCRIPTION": "Estado: {{taskStatus }}. Descripción: {{taskDescription}}", "PAGE_DESCRIPTION": "Estado: {{taskStatus }}. Descripción: {{taskDescription}}",
"SECTION_NAME": "Detalles de tarea", "SECTION_NAME": "Tarea",
"LINK_TASKBOARD": "Panel de tareas", "LINK_TASKBOARD": "Panel de tareas",
"TITLE_LINK_TASKBOARD": "Ir al panel de tareas", "TITLE_LINK_TASKBOARD": "Ir al panel de tareas",
"PLACEHOLDER_SUBJECT": "Escribe el asunto de la nueva tarea", "PLACEHOLDER_SUBJECT": "Escribe el asunto de la nueva tarea",
@ -1189,8 +1336,6 @@
"ORIGIN_US": "Esta tarea pertenece a ", "ORIGIN_US": "Esta tarea pertenece a ",
"TITLE_LINK_GO_ORIGIN": "Ir a historia de usuario", "TITLE_LINK_GO_ORIGIN": "Ir a historia de usuario",
"BLOCKED": "Esta tarea está bloqueada", "BLOCKED": "Esta tarea está bloqueada",
"PREVIOUS": "tarea anterior",
"NEXT": "tarea siguiente",
"TITLE_DELETE_ACTION": "Eliminar Tarea", "TITLE_DELETE_ACTION": "Eliminar Tarea",
"LIGHTBOX_TITLE_BLOKING_TASK": "Tarea bloqueada", "LIGHTBOX_TITLE_BLOKING_TASK": "Tarea bloqueada",
"FIELDS": { "FIELDS": {
@ -1228,16 +1373,13 @@
"PAGE_TITLE": "Peticiones - {{projectName}}", "PAGE_TITLE": "Peticiones - {{projectName}}",
"PAGE_DESCRIPTION": "El panel de peticiones del proyecto {{projectName}}: {{projectDescription}}\n", "PAGE_DESCRIPTION": "El panel de peticiones del proyecto {{projectName}}: {{projectDescription}}\n",
"LIST_SECTION_NAME": "Peticiones", "LIST_SECTION_NAME": "Peticiones",
"SECTION_NAME": "Detalles de petición", "SECTION_NAME": "Petición",
"ACTION_NEW_ISSUE": "+ NUEVA PETICIÓN", "ACTION_NEW_ISSUE": "+ NUEVA PETICIÓN",
"ACTION_PROMOTE_TO_US": "Promover a Historia de Usuario", "ACTION_PROMOTE_TO_US": "Promover a Historia de Usuario",
"PLACEHOLDER_FILTER_NAME": "Escribe un nombre para el filtro y pulsa enter",
"PROMOTED": "Esta petición ha sido promovida a la historia:", "PROMOTED": "Esta petición ha sido promovida a la historia:",
"EXTERNAL_REFERENCE": "Esta petición ha sido creada a partir de ", "EXTERNAL_REFERENCE": "Esta petición ha sido creada a partir de ",
"GO_TO_EXTERNAL_REFERENCE": "Ir al origen", "GO_TO_EXTERNAL_REFERENCE": "Ir al origen",
"BLOCKED": "La petición está bloqueada", "BLOCKED": "La petición está bloqueada",
"TITLE_PREVIOUS_ISSUE": "petición anterior",
"TITLE_NEXT_ISSUE": "petición siguiente",
"ACTION_DELETE": "Borrar petición", "ACTION_DELETE": "Borrar petición",
"LIGHTBOX_TITLE_BLOKING_ISSUE": "Petición bloqueada", "LIGHTBOX_TITLE_BLOKING_ISSUE": "Petición bloqueada",
"FIELDS": { "FIELDS": {
@ -1249,28 +1391,6 @@
"TITLE": "Promover esta petición a una nueva historia de usuario", "TITLE": "Promover esta petición a una nueva historia de usuario",
"MESSAGE": "¿Está seguro de que desea crear una nueva Historia de Usuario a partir de esta Petición?" "MESSAGE": "¿Está seguro de que desea crear una nueva Historia de Usuario a partir de esta Petición?"
}, },
"FILTERS": {
"TITLE": "Filtros",
"INPUT_SEARCH_PLACEHOLDER": "Asunto o referencia",
"TITLE_ACTION_SEARCH": "Buscar",
"ACTION_SAVE_CUSTOM_FILTER": "guardar como filtro personalizado",
"BREADCRUMB": "Filtros",
"TITLE_BREADCRUMB": "Filtros",
"CATEGORIES": {
"TYPE": "Tipo",
"STATUS": "Estado",
"SEVERITY": "Gravedad",
"PRIORITIES": "Prioridad",
"TAGS": "Etiquetas",
"ASSIGNED_TO": "Asignado a",
"CREATED_BY": "Creada por",
"CUSTOM_FILTERS": "Filtros personalizados"
},
"CONFIRM_DELETE": {
"TITLE": "Eliminar filtros personalizados",
"MESSAGE": "el filtro personalizado '{{customFilterName}}'"
}
},
"TABLE": { "TABLE": {
"COLUMNS": { "COLUMNS": {
"TYPE": "Tipo", "TYPE": "Tipo",
@ -1316,6 +1436,7 @@
"SEARCH": { "SEARCH": {
"PAGE_TITLE": "Buscar - {{projectName}}", "PAGE_TITLE": "Buscar - {{projectName}}",
"PAGE_DESCRIPTION": "Busca cualquier cosa: historias de usuario, peticiones, tareas o páginas del wiki en el proyecto {{projectName}}: {{projectDescription}}", "PAGE_DESCRIPTION": "Busca cualquier cosa: historias de usuario, peticiones, tareas o páginas del wiki en el proyecto {{projectName}}: {{projectDescription}}",
"FILTER_EPICS": "Épicas",
"FILTER_USER_STORIES": "Historias de Usuario", "FILTER_USER_STORIES": "Historias de Usuario",
"FILTER_ISSUES": "Peticiones", "FILTER_ISSUES": "Peticiones",
"FILTER_TASKS": "Tareas", "FILTER_TASKS": "Tareas",
@ -1397,16 +1518,16 @@
"WIZARD": { "WIZARD": {
"SECTION_TITLE_CREATE_PROJECT": "Crear Proyecto", "SECTION_TITLE_CREATE_PROJECT": "Crear Proyecto",
"CREATE_PROJECT_TEXT": "Fresco y claro. ¡Es emocionante!", "CREATE_PROJECT_TEXT": "Fresco y claro. ¡Es emocionante!",
"CHOOSE_TEMPLATE": "Which template fits your project best?", "CHOOSE_TEMPLATE": "¿Que plantilla se ajusta mejor con tu proyecto?",
"CHOOSE_TEMPLATE_TITLE": "More info about project templates", "CHOOSE_TEMPLATE_TITLE": "Mas informacion acerca de la plantillas del proyecto",
"CHOOSE_TEMPLATE_INFO": "More info", "CHOOSE_TEMPLATE_INFO": "Mas información",
"PROJECT_DETAILS": "Project Details", "PROJECT_DETAILS": "Detalles del proyecto",
"PUBLIC_PROJECT": "Public Project", "PUBLIC_PROJECT": "Proyecto público",
"PRIVATE_PROJECT": "Private Project", "PRIVATE_PROJECT": "Proyecto privado",
"CREATE_PROJECT": "Crear proyecto", "CREATE_PROJECT": "Crear proyecto",
"MAX_PRIVATE_PROJECTS": "You've reached the maximum number of private projects", "MAX_PRIVATE_PROJECTS": "Has alcanzado el número máximo de proyectos privados",
"MAX_PUBLIC_PROJECTS": "Unfortunately, you've reached the maximum number of public projects", "MAX_PUBLIC_PROJECTS": "Desafortunadamente, has alcanzado el número máximo de proyectos públicos",
"CHANGE_PLANS": "change plans" "CHANGE_PLANS": "cambiar planes"
}, },
"WIKI": { "WIKI": {
"PAGE_TITLE": "{{wikiPageName}} - Wiki - {{projectName}}", "PAGE_TITLE": "{{wikiPageName}} - Wiki - {{projectName}}",
@ -1415,15 +1536,26 @@
"PLACEHOLDER_PAGE": "Escribe el contenido de tu página", "PLACEHOLDER_PAGE": "Escribe el contenido de tu página",
"REMOVE": "Eliminar esta página del wiki", "REMOVE": "Eliminar esta página del wiki",
"DELETE_LIGHTBOX_TITLE": "Eliminar Página del Wiki", "DELETE_LIGHTBOX_TITLE": "Eliminar Página del Wiki",
"DELETE_LINK_TITLE": "Delete Wiki link", "DELETE_LINK_TITLE": "Eliminar enlace de la Wiki",
"NAVIGATION": { "NAVIGATION": {
"SECTION_NAME": "Enlaces", "HOME": "Principal",
"ACTION_ADD_LINK": "Añadir enlace" "SECTION_NAME": "BOOKMARKS",
"ACTION_ADD_LINK": "Add bookmark",
"ALL_PAGES": "All wiki pages"
}, },
"SUMMARY": { "SUMMARY": {
"TIMES_EDITED": "veces <br />editada", "TIMES_EDITED": "veces <br />editada",
"LAST_EDIT": "última <br />edición", "LAST_EDIT": "última <br />edición",
"LAST_MODIFICATION": "ultima modificación" "LAST_MODIFICATION": "ultima modificación"
},
"SECTION_PAGES_LIST": "Todas",
"PAGES_LIST_COLUMNS": {
"TITLE": "Título",
"EDITIONS": "Ediciones",
"CREATED": "Creado",
"MODIFIED": "Modificado",
"CREATOR": "Creador",
"LAST_MODIFIER": "Ultimo modificador"
} }
}, },
"HINTS": { "HINTS": {
@ -1447,6 +1579,8 @@
"TASK_CREATED_WITH_US": "{{username}} ha creado una nueva tarea {{obj_name}} en {{project_name}} que proviene de la historia {{us_name}}", "TASK_CREATED_WITH_US": "{{username}} ha creado una nueva tarea {{obj_name}} en {{project_name}} que proviene de la historia {{us_name}}",
"WIKI_CREATED": "{{username}} ha creado una nueva página de wiki {{obj_name}} en {{project_name}}\n", "WIKI_CREATED": "{{username}} ha creado una nueva página de wiki {{obj_name}} en {{project_name}}\n",
"MILESTONE_CREATED": "{{username}} ha creado un nuevo sprint {{obj_name}} en {{project_name}}", "MILESTONE_CREATED": "{{username}} ha creado un nuevo sprint {{obj_name}} en {{project_name}}",
"EPIC_CREATED": "{{username}} has created a new epic {{obj_name}} in {{project_name}}",
"EPIC_RELATED_USERSTORY_CREATED": "{{username}} has related the userstory {{related_us_name}} to the epic {{epic_name}} in {{project_name}}",
"NEW_PROJECT": "{{username}} creó el proyecto {{project_name}}", "NEW_PROJECT": "{{username}} creó el proyecto {{project_name}}",
"MILESTONE_UPDATED": "{{username}} ha actualizado el sprint {{obj_name}}", "MILESTONE_UPDATED": "{{username}} ha actualizado el sprint {{obj_name}}",
"US_UPDATED": "{{username}} ha actualizado el atributo \"{{field_name}}\" de la historia {{obj_name}}", "US_UPDATED": "{{username}} ha actualizado el atributo \"{{field_name}}\" de la historia {{obj_name}}",
@ -1459,9 +1593,13 @@
"TASK_UPDATED_WITH_US": "{{username}} ha actualizado el atributo \"{{field_name}}\" de la tarea {{obj_name}} que proviene de la historia {{us_name}}", "TASK_UPDATED_WITH_US": "{{username}} ha actualizado el atributo \"{{field_name}}\" de la tarea {{obj_name}} que proviene de la historia {{us_name}}",
"TASK_UPDATED_WITH_US_NEW_VALUE": "{{username}} ha actualizado el atributo \"{{field_name}}\" de la tarea {{obj_name}} que pertenece a la historia {{us_name}} a {{new_value}}", "TASK_UPDATED_WITH_US_NEW_VALUE": "{{username}} ha actualizado el atributo \"{{field_name}}\" de la tarea {{obj_name}} que pertenece a la historia {{us_name}} a {{new_value}}",
"WIKI_UPDATED": "{{username}} ha actualizado la página del wiki {{obj_name}}", "WIKI_UPDATED": "{{username}} ha actualizado la página del wiki {{obj_name}}",
"EPIC_UPDATED": "{{username}} has updated the attribute \"{{field_name}}\" of the epic {{obj_name}}",
"EPIC_UPDATED_WITH_NEW_VALUE": "{{username}} has updated the attribute \"{{field_name}}\" of the epic {{obj_name}} to {{new_value}}",
"EPIC_UPDATED_WITH_NEW_COLOR": "{{username}} has updated the \"{{field_name}}\" of the epic {{obj_name}} to <span class=\"new-color\" style=\"background: {{new_value}}\"></span>",
"NEW_COMMENT_US": "{{username}} ha añadido un comentado en la historia {{obj_name}}", "NEW_COMMENT_US": "{{username}} ha añadido un comentado en la historia {{obj_name}}",
"NEW_COMMENT_ISSUE": "{{username}} ha añadido un comentado en la petición {{obj_name}}", "NEW_COMMENT_ISSUE": "{{username}} ha añadido un comentado en la petición {{obj_name}}",
"NEW_COMMENT_TASK": "{{username}} ha añadido un comentado en la tarea {{obj_name}}", "NEW_COMMENT_TASK": "{{username}} ha añadido un comentado en la tarea {{obj_name}}",
"NEW_COMMENT_EPIC": "{{username}} has commented in the epic {{obj_name}}",
"NEW_MEMBER": "{{project_name}} tiene un nuevo miembro", "NEW_MEMBER": "{{project_name}} tiene un nuevo miembro",
"US_ADDED_MILESTONE": "{{username}} ha añadido la historia {{obj_name}} a {{sprint_name}}", "US_ADDED_MILESTONE": "{{username}} ha añadido la historia {{obj_name}} a {{sprint_name}}",
"US_MOVED": "{{username}} ha movido la historia {{obj_name}}", "US_MOVED": "{{username}} ha movido la historia {{obj_name}}",

View File

@ -35,6 +35,8 @@
"ONE_ITEM_LINE": "Yksi riviä kohti...", "ONE_ITEM_LINE": "Yksi riviä kohti...",
"NEW_BULK": "Lisää monta", "NEW_BULK": "Lisää monta",
"RELATED_TASKS": "Liittyvät tehtävät", "RELATED_TASKS": "Liittyvät tehtävät",
"PREVIOUS": "Previous",
"NEXT": "Seuraava",
"LOGOUT": "Kirjaudu ulos", "LOGOUT": "Kirjaudu ulos",
"EXTERNAL_USER": "ulkoinen käyttäjä", "EXTERNAL_USER": "ulkoinen käyttäjä",
"GENERIC_ERROR": "Oompa Loompas havaitsivat virheen {{error}}.", "GENERIC_ERROR": "Oompa Loompas havaitsivat virheen {{error}}.",
@ -45,6 +47,11 @@
"CAPSLOCK_WARNING": "Be careful! You are using capital letters in an input field that is case sensitive.", "CAPSLOCK_WARNING": "Be careful! You are using capital letters in an input field that is case sensitive.",
"CONFIRM_CLOSE_EDIT_MODE_TITLE": "Are you sure you want to close the edit mode?", "CONFIRM_CLOSE_EDIT_MODE_TITLE": "Are you sure you want to close the edit mode?",
"CONFIRM_CLOSE_EDIT_MODE_MESSAGE": "Remember that if you close the edit mode without saving all the changes will be lost", "CONFIRM_CLOSE_EDIT_MODE_MESSAGE": "Remember that if you close the edit mode without saving all the changes will be lost",
"RELATED_USERSTORIES": "Related user stories",
"CARD": {
"ASSIGN_TO": "Assign To",
"EDIT": "Edit card"
},
"FORM_ERRORS": { "FORM_ERRORS": {
"DEFAULT_MESSAGE": "Tämä arvo vaikuttaa virheelliseltä.", "DEFAULT_MESSAGE": "Tämä arvo vaikuttaa virheelliseltä.",
"TYPE_EMAIL": "Tämän pitäisi olla toimiva sähköpostiosoite.", "TYPE_EMAIL": "Tämän pitäisi olla toimiva sähköpostiosoite.",
@ -115,8 +122,9 @@
"USER_STORY": "Käyttäjätarina", "USER_STORY": "Käyttäjätarina",
"TASK": "Task", "TASK": "Task",
"ISSUE": "Issue", "ISSUE": "Issue",
"EPIC": "Epic",
"TAGS": { "TAGS": {
"PLACEHOLDER": "Anna avainsana...", "PLACEHOLDER": "Enter tag",
"DELETE": "Poista avainsana", "DELETE": "Poista avainsana",
"ADD": "Lisää avainsana" "ADD": "Lisää avainsana"
}, },
@ -193,12 +201,29 @@
"CONFIRM_DELETE": "Remeber that all values in this custom field will be deleted.\n Are you sure you want to continue?" "CONFIRM_DELETE": "Remeber that all values in this custom field will be deleted.\n Are you sure you want to continue?"
}, },
"FILTERS": { "FILTERS": {
"TITLE": "suodattimet", "TITLE": "Suodattimet",
"INPUT_PLACEHOLDER": "Aihe tai viittaus", "INPUT_PLACEHOLDER": "Aihe tai viittaus",
"TITLE_ACTION_FILTER_BUTTON": "hae", "TITLE_ACTION_FILTER_BUTTON": "hae",
"BREADCRUMB_TITLE": "takaisin kategorioihin", "INPUT_SEARCH_PLACEHOLDER": "Otsikko tai viittaus",
"BREADCRUMB_FILTERS": "Suodattimet", "TITLE_ACTION_SEARCH": "Hae",
"BREADCRUMB_STATUS": "tila" "ACTION_SAVE_CUSTOM_FILTER": "tallenna omaksi suodattimeksi",
"PLACEHOLDER_FILTER_NAME": "Anna suodattimen nimi ja paina enter",
"APPLIED_FILTERS_NUM": "filters applied",
"CATEGORIES": {
"TYPE": "Tyyppi",
"STATUS": "Tila",
"SEVERITY": "Vakavuus",
"PRIORITIES": "Kiireellisyydet",
"TAGS": "Avainsanat",
"ASSIGNED_TO": "Tekijä",
"CREATED_BY": "Luoja",
"CUSTOM_FILTERS": "Omat suodattimet",
"EPIC": "Epic"
},
"CONFIRM_DELETE": {
"TITLE": "Poista oma suodatin",
"MESSAGE": "oma suodatin '{{customFilterName}}'"
}
}, },
"WYSIWYG": { "WYSIWYG": {
"H1_BUTTON": "Päätason otsikko", "H1_BUTTON": "Päätason otsikko",
@ -228,9 +253,18 @@
"PREVIEW_BUTTON": "Esikatselu", "PREVIEW_BUTTON": "Esikatselu",
"EDIT_BUTTON": "Muokkaa", "EDIT_BUTTON": "Muokkaa",
"ATTACH_FILE_HELP": "Attach files by dragging & dropping on the textarea above.", "ATTACH_FILE_HELP": "Attach files by dragging & dropping on the textarea above.",
"ATTACH_FILE_HELP_SAVE_FIRST": "Save first before if you want to attach files by dragging & dropping on the textarea above.",
"MARKDOWN_HELP": "Merkintätavan ohjeet" "MARKDOWN_HELP": "Merkintätavan ohjeet"
}, },
"PERMISIONS_CATEGORIES": { "PERMISIONS_CATEGORIES": {
"EPICS": {
"NAME": "Epics",
"VIEW_EPICS": "View epics",
"ADD_EPICS": "Add epics",
"MODIFY_EPICS": "Modify epics",
"COMMENT_EPICS": "Comment epics",
"DELETE_EPICS": "Delete epics"
},
"SPRINTS": { "SPRINTS": {
"NAME": "Kierrokset", "NAME": "Kierrokset",
"VIEW_SPRINTS": "Katso kierroksia", "VIEW_SPRINTS": "Katso kierroksia",
@ -243,6 +277,7 @@
"VIEW_USER_STORIES": "Katso käyttäjätarinoita", "VIEW_USER_STORIES": "Katso käyttäjätarinoita",
"ADD_USER_STORIES": "Lisää käyttäjätarinoita", "ADD_USER_STORIES": "Lisää käyttäjätarinoita",
"MODIFY_USER_STORIES": "Muokkaa käyttäjätarinoita", "MODIFY_USER_STORIES": "Muokkaa käyttäjätarinoita",
"COMMENT_USER_STORIES": "Comment user stories",
"DELETE_USER_STORIES": "Poista käyttäjätarinoita" "DELETE_USER_STORIES": "Poista käyttäjätarinoita"
}, },
"TASKS": { "TASKS": {
@ -250,6 +285,7 @@
"VIEW_TASKS": "Katsot tehtäviä", "VIEW_TASKS": "Katsot tehtäviä",
"ADD_TASKS": "Lisää tehtäviä", "ADD_TASKS": "Lisää tehtäviä",
"MODIFY_TASKS": "Muokkaa tehtäviä", "MODIFY_TASKS": "Muokkaa tehtäviä",
"COMMENT_TASKS": "Comment tasks",
"DELETE_TASKS": "Poista tehtäviä" "DELETE_TASKS": "Poista tehtäviä"
}, },
"ISSUES": { "ISSUES": {
@ -257,6 +293,7 @@
"VIEW_ISSUES": "Katso pyyntöjä", "VIEW_ISSUES": "Katso pyyntöjä",
"ADD_ISSUES": "Lisää pyyntöjä", "ADD_ISSUES": "Lisää pyyntöjä",
"MODIFY_ISSUES": "Muokkaa pyyntöjä", "MODIFY_ISSUES": "Muokkaa pyyntöjä",
"COMMENT_ISSUES": "Comment issues",
"DELETE_ISSUES": "Poista pyyntöjä" "DELETE_ISSUES": "Poista pyyntöjä"
}, },
"WIKI": { "WIKI": {
@ -366,6 +403,41 @@
"WATCHING_SECTION": "Watching", "WATCHING_SECTION": "Watching",
"DASHBOARD": "Projects Dashboard" "DASHBOARD": "Projects Dashboard"
}, },
"EPICS": {
"TITLE": "EPICS",
"SECTION_NAME": "Epics",
"EPIC": "EPIC",
"PAGE_TITLE": "Epics - {{projectName}}",
"PAGE_DESCRIPTION": "The epics list of the project {{projectName}}: {{projectDescription}}",
"DASHBOARD": {
"ADD": "+ ADD EPIC",
"UNASSIGNED": "Tekijä puuttuu"
},
"EMPTY": {
"TITLE": "It looks like there aren't any epics yet",
"EXPLANATION": "Epics are items at a higher level that encompass user stories.<br />Epics are at the top of the hierarchy and can be used to group user stories together.",
"HELP": "Learn more about epics"
},
"TABLE": {
"VOTES": "Ääniä",
"NAME": "Nimi",
"PROJECT": "Projekti",
"SPRINT": "Kierros",
"ASSIGNED_TO": "Assigned",
"STATUS": "Tila",
"PROGRESS": "Progress",
"VIEW_OPTIONS": "View options"
},
"CREATE": {
"TITLE": "New Epic",
"PLACEHOLDER_DESCRIPTION": "Please add descriptive text to help others better understand this epic",
"TEAM_REQUIREMENT": "Team requirement",
"CLIENT_REQUIREMENT": "Client requirement",
"BLOCKED": "Suljettu",
"BLOCKED_NOTE_PLACEHOLDER": "Why is this epic blocked?",
"CREATE_EPIC": "Create epic"
}
},
"PROJECTS": { "PROJECTS": {
"PAGE_TITLE": "My projects - Taiga", "PAGE_TITLE": "My projects - Taiga",
"PAGE_DESCRIPTION": "A list with all your projects, you can reorder or create a new one.", "PAGE_DESCRIPTION": "A list with all your projects, you can reorder or create a new one.",
@ -402,7 +474,8 @@
"ADMIN": { "ADMIN": {
"COMMON": { "COMMON": {
"TITLE_ACTION_EDIT_VALUE": "Muokkaa arvoa", "TITLE_ACTION_EDIT_VALUE": "Muokkaa arvoa",
"TITLE_ACTION_DELETE_VALUE": "Poista arvo" "TITLE_ACTION_DELETE_VALUE": "Poista arvo",
"TITLE_ACTION_DELETE_TAG": "Poista avainsana"
}, },
"HELP": "Tarvitsetko apua? Katso tukisivuilta.", "HELP": "Tarvitsetko apua? Katso tukisivuilta.",
"PROJECT_DEFAULT_VALUES": { "PROJECT_DEFAULT_VALUES": {
@ -435,6 +508,8 @@
"TITLE": "Modulit", "TITLE": "Modulit",
"ENABLE": "Aktivoi", "ENABLE": "Aktivoi",
"DISABLE": "Passivoi", "DISABLE": "Passivoi",
"EPICS": "Epics",
"EPICS_DESCRIPTION": "Visualize and manage the most strategic part of your project",
"BACKLOG": "Odottavat", "BACKLOG": "Odottavat",
"BACKLOG_DESCRIPTION": "Hallinnoi käyttäjätarinoita: järjestele ja priorisoi työtä.", "BACKLOG_DESCRIPTION": "Hallinnoi käyttäjätarinoita: järjestele ja priorisoi työtä.",
"NUMBER_SPRINTS": "Expected number of sprints", "NUMBER_SPRINTS": "Expected number of sprints",
@ -497,6 +572,7 @@
"REGENERATE_SUBTITLE": "Jos muutata CSV-datan URLia, edellien lakkaa toimimasta. Oletko varma?" "REGENERATE_SUBTITLE": "Jos muutata CSV-datan URLia, edellien lakkaa toimimasta. Oletko varma?"
}, },
"CSV": { "CSV": {
"SECTION_TITLE_EPIC": "epics reports",
"SECTION_TITLE_US": "käyttäjätarinoiden raportit", "SECTION_TITLE_US": "käyttäjätarinoiden raportit",
"SECTION_TITLE_TASK": "tehtävien raportit", "SECTION_TITLE_TASK": "tehtävien raportit",
"SECTION_TITLE_ISSUE": "pyyntöjen raportit", "SECTION_TITLE_ISSUE": "pyyntöjen raportit",
@ -509,6 +585,8 @@
"CUSTOM_FIELDS": { "CUSTOM_FIELDS": {
"TITLE": "Omat kentät", "TITLE": "Omat kentät",
"SUBTITLE": "Määritele omia kenttiä käyttäjätarinoihin, tehtäviin ja pyytöihin", "SUBTITLE": "Määritele omia kenttiä käyttäjätarinoihin, tehtäviin ja pyytöihin",
"EPIC_DESCRIPTION": "Epics custom fields",
"EPIC_ADD": "Add a custom field in epics",
"US_DESCRIPTION": "Käyttäjätarinoiden omat kentät", "US_DESCRIPTION": "Käyttäjätarinoiden omat kentät",
"US_ADD": "Lisää käyttäjätarinoihin oma kenttä", "US_ADD": "Lisää käyttäjätarinoihin oma kenttä",
"TASK_DESCRIPTION": "Tehtävien omat kentät", "TASK_DESCRIPTION": "Tehtävien omat kentät",
@ -546,7 +624,8 @@
"PROJECT_VALUES_STATUS": { "PROJECT_VALUES_STATUS": {
"TITLE": "Tila", "TITLE": "Tila",
"SUBTITLE": "Määrittele tilat joiden kautta käyttäjätarinasi, tehtäväsi ja pyyntösi kulkevat", "SUBTITLE": "Määrittele tilat joiden kautta käyttäjätarinasi, tehtäväsi ja pyyntösi kulkevat",
"US_TITLE": "Kt tilat", "EPIC_TITLE": "Epic Statuses",
"US_TITLE": "User Story Statuses",
"TASK_TITLE": "Tehtävien tilat", "TASK_TITLE": "Tehtävien tilat",
"ISSUE_TITLE": "Pyyntöjen tilat" "ISSUE_TITLE": "Pyyntöjen tilat"
}, },
@ -556,6 +635,17 @@
"ISSUE_TITLE": "Pyyntöjen tyypit", "ISSUE_TITLE": "Pyyntöjen tyypit",
"ACTION_ADD": "Lisää uusi {{objName}}" "ACTION_ADD": "Lisää uusi {{objName}}"
}, },
"PROJECT_VALUES_TAGS": {
"TITLE": "Avainsanat",
"SUBTITLE": "View and edit the color of your tags",
"EMPTY": "Currently there are no tags",
"EMPTY_SEARCH": "It looks like nothing was found with your search criteria",
"ACTION_ADD": "Lisää avainsana",
"NEW_TAG": "New tag",
"MIXING_HELP_TEXT": "Select the tags that you want to merge",
"MIXING_MERGE": "Merge Tags",
"SELECTED": "Selected"
},
"ROLES": { "ROLES": {
"PAGE_TITLE": "Roles - {{projectName}}", "PAGE_TITLE": "Roles - {{projectName}}",
"WARNING_NO_ROLE": "Ole varovainen, yksikään rooli projektissasi ei voi arvioida käyttäjätarinoidesi kokoa", "WARNING_NO_ROLE": "Ole varovainen, yksikään rooli projektissasi ei voi arvioida käyttäjätarinoidesi kokoa",
@ -588,6 +678,10 @@
"SECTION_NAME": "Github", "SECTION_NAME": "Github",
"PAGE_TITLE": "Github - {{projectName}}" "PAGE_TITLE": "Github - {{projectName}}"
}, },
"GOGS": {
"SECTION_NAME": "Gogs",
"PAGE_TITLE": "Gogs - {{projectName}}"
},
"WEBHOOKS": { "WEBHOOKS": {
"PAGE_TITLE": "Webhooks - {{projectName}}", "PAGE_TITLE": "Webhooks - {{projectName}}",
"SECTION_NAME": "Webhookit", "SECTION_NAME": "Webhookit",
@ -643,13 +737,14 @@
"DEFAULT_DELETE_MESSAGE": "kutsu sähköpostiin {{email}}" "DEFAULT_DELETE_MESSAGE": "kutsu sähköpostiin {{email}}"
}, },
"DEFAULT_VALUES": { "DEFAULT_VALUES": {
"LABEL_EPIC_STATUS": "Default value for epic status selector",
"LABEL_US_STATUS": "Default value for user story status selector",
"LABEL_POINTS": "Oletukset pisteiden valintaan", "LABEL_POINTS": "Oletukset pisteiden valintaan",
"LABEL_US": "Oletukset käyttäjätarinoiden tiloiksi",
"LABEL_TASK_STATUS": "Oletukset tehtävien tilaksi", "LABEL_TASK_STATUS": "Oletukset tehtävien tilaksi",
"LABEL_PRIORITY": "Oletus arvo tärkeyden valiintaan",
"LABEL_SEVERITY": "Oletukset vakavuudeksi",
"LABEL_ISSUE_TYPE": "Oletukset pyyntöjen tyypeiksi", "LABEL_ISSUE_TYPE": "Oletukset pyyntöjen tyypeiksi",
"LABEL_ISSUE_STATUS": "Oletukset pyyntöjen statuksiksi" "LABEL_ISSUE_STATUS": "Oletukset pyyntöjen statuksiksi",
"LABEL_PRIORITY": "Oletus arvo tärkeyden valiintaan",
"LABEL_SEVERITY": "Oletukset vakavuudeksi"
}, },
"STATUS": { "STATUS": {
"PLACEHOLDER_WRITE_STATUS_NAME": "Anna uuden tilan nimi" "PLACEHOLDER_WRITE_STATUS_NAME": "Anna uuden tilan nimi"
@ -681,7 +776,8 @@
"PRIORITIES": "Tärkeydet", "PRIORITIES": "Tärkeydet",
"SEVERITIES": "Vakavuudet", "SEVERITIES": "Vakavuudet",
"TYPES": "Tyypit", "TYPES": "Tyypit",
"CUSTOM_FIELDS": "Omat kentät" "CUSTOM_FIELDS": "Omat kentät",
"TAGS": "Avainsanat"
}, },
"SUBMENU_PROJECT_PROFILE": { "SUBMENU_PROJECT_PROFILE": {
"TITLE": "Projektin profiili" "TITLE": "Projektin profiili"
@ -751,6 +847,8 @@
"FILTER_TYPE_ALL_TITLE": "Show all", "FILTER_TYPE_ALL_TITLE": "Show all",
"FILTER_TYPE_PROJECTS": "Projektit", "FILTER_TYPE_PROJECTS": "Projektit",
"FILTER_TYPE_PROJECT_TITLES": "Show only projects", "FILTER_TYPE_PROJECT_TITLES": "Show only projects",
"FILTER_TYPE_EPICS": "Epics",
"FILTER_TYPE_EPIC_TITLES": "Show only epics",
"FILTER_TYPE_USER_STORIES": "Stories", "FILTER_TYPE_USER_STORIES": "Stories",
"FILTER_TYPE_USER_STORIES_TITLES": "Show only user stories", "FILTER_TYPE_USER_STORIES_TITLES": "Show only user stories",
"FILTER_TYPE_TASKS": "Tehtävät", "FILTER_TYPE_TASKS": "Tehtävät",
@ -950,8 +1048,8 @@
"CREATE_MEMBER": { "CREATE_MEMBER": {
"PLACEHOLDER_INVITATION_TEXT": "(Vapaaehtoinen) Lisää oma kuvaus kutsuusi uusille jäsenille ;-)", "PLACEHOLDER_INVITATION_TEXT": "(Vapaaehtoinen) Lisää oma kuvaus kutsuusi uusille jäsenille ;-)",
"PLACEHOLDER_TYPE_EMAIL": "Anna sähköposti", "PLACEHOLDER_TYPE_EMAIL": "Anna sähköposti",
"LIMIT_USERS_WARNING_MESSAGE_FOR_OWNER": "Unfortunately, this project can't have more than <strong>{{maxMembers}}</strong> members.<br> If you would like to increase the current limit, please contact the administrator.", "LIMIT_USERS_WARNING_MESSAGE_FOR_OWNER": "You are about to reach the maximum number of members allowed for this project, <strong>{{maxMembers}}</strong> members. If you would like to increase the current limit, please contact the administrator.",
"LIMIT_USERS_WARNING_MESSAGE": "Unfortunately, this project can't have more than <strong>{{maxMembers}}</strong> members." "LIMIT_USERS_WARNING_MESSAGE": "You are about to reach the maximum number of members allowed for this project, <strong>{{maxMembers}}</strong> members."
}, },
"LEAVE_PROJECT_WARNING": { "LEAVE_PROJECT_WARNING": {
"TITLE": "Unfortunately, this project can't be left without an owner", "TITLE": "Unfortunately, this project can't be left without an owner",
@ -970,10 +1068,30 @@
"BUTTON": "Ask this project member to become the new project owner" "BUTTON": "Ask this project member to become the new project owner"
} }
}, },
"EPIC": {
"PAGE_TITLE": "{{epicSubject}} - Epic {{epicRef}} - {{projectName}}",
"PAGE_DESCRIPTION": "Status: {{epicStatus }}. Description: {{epicDescription}}",
"SECTION_NAME": "Epic",
"TITLE_LIGHTBOX_UNLINK_RELATED_USERSTORY": "Unlink related userstory",
"MSG_LIGHTBOX_UNLINK_RELATED_USERSTORY": "It will delete the link to the related userstory '{{subject}}'",
"ERROR_UNLINK_RELATED_USERSTORY": "We have not been able to unlink: {{errorMessage}}",
"CREATE_RELATED_USERSTORIES": "Create a relationship with",
"NEW_USERSTORY": "Uusi käyttäjätarina",
"EXISTING_USERSTORY": "Existing user story",
"CHOOSE_PROJECT_FOR_CREATION": "What's the project?",
"SUBJECT": "Aihe",
"SUBJECT_BULK_MODE": "Subject (bulk insert)",
"CHOOSE_PROJECT_FROM": "What's the project?",
"CHOOSE_USERSTORY": "What's the user story?",
"NO_USERSTORIES": "This project has no User Stories yet. Please select another project.",
"FILTER_USERSTORIES": "Filter user stories",
"LIGHTBOX_TITLE_BLOKING_EPIC": "Blocking epic",
"ACTION_DELETE": "Delete epic"
},
"US": { "US": {
"PAGE_TITLE": "{{userStorySubject}} - User Story {{userStoryRef}} - {{projectName}}", "PAGE_TITLE": "{{userStorySubject}} - User Story {{userStoryRef}} - {{projectName}}",
"PAGE_DESCRIPTION": "Status: {{userStoryStatus }}. Completed {{userStoryProgressPercentage}}% ({{userStoryClosedTasks}} of {{userStoryTotalTasks}} tasks closed). Points: {{userStoryPoints}}. Description: {{userStoryDescription}}", "PAGE_DESCRIPTION": "Status: {{userStoryStatus }}. Completed {{userStoryProgressPercentage}}% ({{userStoryClosedTasks}} of {{userStoryTotalTasks}} tasks closed). Points: {{userStoryPoints}}. Description: {{userStoryDescription}}",
"SECTION_NAME": "Käyttäjätarinan tiedot", "SECTION_NAME": "Käyttäjätarina",
"LINK_TASKBOARD": "Tehtävätaulu", "LINK_TASKBOARD": "Tehtävätaulu",
"TITLE_LINK_TASKBOARD": "Siirry tehtävätauluun", "TITLE_LINK_TASKBOARD": "Siirry tehtävätauluun",
"TOTAL_POINTS": "total points", "TOTAL_POINTS": "total points",
@ -984,14 +1102,23 @@
"EXTERNAL_REFERENCE": "Tämä Kt oon luotu täältä: ", "EXTERNAL_REFERENCE": "Tämä Kt oon luotu täältä: ",
"GO_TO_EXTERNAL_REFERENCE": "Palaa alkuun", "GO_TO_EXTERNAL_REFERENCE": "Palaa alkuun",
"BLOCKED": "Tämä käyttäjätarina on suljettu", "BLOCKED": "Tämä käyttäjätarina on suljettu",
"PREVIOUS": "edellinen käyttäjätarina",
"NEXT": "seuraava käyttäjätarina",
"TITLE_DELETE_ACTION": "Poista käyttäjätarina", "TITLE_DELETE_ACTION": "Poista käyttäjätarina",
"LIGHTBOX_TITLE_BLOKING_US": "Meitä estää", "LIGHTBOX_TITLE_BLOKING_US": "Meitä estää",
"TASK_COMPLETED": "{{totalClosedTasks}}/{{totalTasks}} tehtyä tehtävää", "TASK_COMPLETED": "{{totalClosedTasks}}/{{totalTasks}} tehtyä tehtävää",
"ASSIGN": "Käyttäjätarinan tekijä", "ASSIGN": "Käyttäjätarinan tekijä",
"NOT_ESTIMATED": "Ei arvioitu", "NOT_ESTIMATED": "Ei arvioitu",
"TOTAL_US_POINTS": "Kt pisteet yhteensä", "TOTAL_US_POINTS": "Kt pisteet yhteensä",
"TRIBE": {
"PUBLISH": "Publish as Gig in Taiga Tribe",
"PUBLISH_INFO": "More info",
"PUBLISH_TITLE": "More info on publishing in Taiga Tribe",
"PUBLISHED_AS_GIG": "Story published as Gig in Taiga Tribe",
"EDIT_LINK": "Edit link",
"CLOSE": "Close",
"SYNCHRONIZE_LINK": "synchronize with Taiga Tribe",
"PUBLISH_MORE_INFO_TITLE": "Do you need somebody for this task?",
"PUBLISH_MORE_INFO_TEXT": "<p>If you need help with a particular piece of work you can easily create gigs on<a href='taigatribe.com' title='Taiga Tribe'> Taiga Tribe </a> and receive help from all over the world. You will be able to control and manage the gig enjoying a great community eager to contribute.</p><p><a href='taigatribe.com' title='Taiga Tribe'> TaigaTribe </a> was born as a Taiga sibling. Both platforms can live separately but we believe that there is much power in using them combined so we are making sure the integration works like a charm.</p>"
},
"FIELDS": { "FIELDS": {
"TEAM_REQUIREMENT": "Tiimin vaatimus", "TEAM_REQUIREMENT": "Tiimin vaatimus",
"CLIENT_REQUIREMENT": "Asiakkaan vaatimus", "CLIENT_REQUIREMENT": "Asiakkaan vaatimus",
@ -999,28 +1126,47 @@
} }
}, },
"COMMENTS": { "COMMENTS": {
"DELETED_INFO": "{{user}} poisti kommentin {{date}}", "DELETED_INFO": "Comment deleted by {{user}}",
"TITLE": "Kommentit", "TITLE": "Kommentit",
"COMMENTS_COUNT": "{{comments}} Comments",
"ORDER": "Order",
"OLDER_FIRST": "Older first",
"RECENT_FIRST": "Recent first",
"COMMENT": "Kommentti", "COMMENT": "Kommentti",
"EDIT_COMMENT": "Edit comment",
"EDITED_COMMENT": "Edited:",
"SHOW_HISTORY": "View historic",
"TYPE_NEW_COMMENT": "Lisää uusi kommentti tässä", "TYPE_NEW_COMMENT": "Lisää uusi kommentti tässä",
"SHOW_DELETED": "Näytä poistettu kommentti", "SHOW_DELETED": "Näytä poistettu kommentti",
"HIDE_DELETED": "Piilota poistettu kommentti", "HIDE_DELETED": "Piilota poistettu kommentti",
"DELETE": "Delete comment", "DELETE": "Delete comment",
"RESTORE": "Palauta kommentti" "RESTORE": "Palauta kommentti",
"HISTORY": {
"TITLE": "Aktiivisuus"
}
}, },
"ACTIVITY": { "ACTIVITY": {
"SHOW_ACTIVITY": "Näytä tapahtumat", "SHOW_ACTIVITY": "Näytä tapahtumat",
"DATETIME": "DD.MM.YY - HH:mm", "DATETIME": "DD.MM.YY - HH:mm",
"SHOW_MORE": "+ Näytä edelliset rivit ({{showMore}} lisää)", "SHOW_MORE": "+ Näytä edelliset rivit ({{showMore}} lisää)",
"TITLE": "Aktiivisuus", "TITLE": "Aktiivisuus",
"ACTIVITIES_COUNT": "{{activities}} Activities",
"REMOVED": "poistettu", "REMOVED": "poistettu",
"ADDED": "lisätty", "ADDED": "lisätty",
"US_POINTS": "Kt pisteet ({{name}})", "TAGS_ADDED": "tags added:",
"NEW_ATTACHMENT": "uusi liite", "TAGS_REMOVED": "tags removed:",
"DELETED_ATTACHMENT": "poistettu liite", "US_POINTS": "{{role}} points",
"UPDATED_ATTACHMENT": "päivitetty liite {{filename}}", "NEW_ATTACHMENT": "new attachment:",
"DELETED_CUSTOM_ATTRIBUTE": "poista oma attribuutti", "DELETED_ATTACHMENT": "deleted attachment:",
"UPDATED_ATTACHMENT": "updated attachment ({{filename}}):",
"CREATED_CUSTOM_ATTRIBUTE": "created custom attribute",
"UPDATED_CUSTOM_ATTRIBUTE": "updated custom attribute",
"SIZE_CHANGE": "Tehty {size, plural, one{muutos} other{# muutosta}}", "SIZE_CHANGE": "Tehty {size, plural, one{muutos} other{# muutosta}}",
"BECAME_DEPRECATED": "became deprecated",
"BECAME_UNDEPRECATED": "became undeprecated",
"TEAM_REQUIREMENT": "Tiimin vaatimus",
"CLIENT_REQUIREMENT": "Asiakkaan vaatimus",
"BLOCKED": "Suljettu",
"VALUES": { "VALUES": {
"YES": "Kyllä", "YES": "Kyllä",
"NO": "ei", "NO": "ei",
@ -1052,12 +1198,14 @@
"TAGS": "avainsanat", "TAGS": "avainsanat",
"ATTACHMENTS": "liitteet", "ATTACHMENTS": "liitteet",
"IS_DEPRECATED": "on vanhentunut", "IS_DEPRECATED": "on vanhentunut",
"IS_NOT_DEPRECATED": "is not deprecated",
"ORDER": "järjestys", "ORDER": "järjestys",
"BACKLOG_ORDER": "odottavien järjestys", "BACKLOG_ORDER": "odottavien järjestys",
"SPRINT_ORDER": "kierroksen järjestys", "SPRINT_ORDER": "kierroksen järjestys",
"KANBAN_ORDER": "kanban järjestys", "KANBAN_ORDER": "kanban järjestys",
"TASKBOARD_ORDER": "Tehtävätaulun järjestys", "TASKBOARD_ORDER": "Tehtävätaulun järjestys",
"US_ORDER": "kt järjestys" "US_ORDER": "kt järjestys",
"COLOR": "väri"
} }
}, },
"BACKLOG": { "BACKLOG": {
@ -1109,7 +1257,8 @@
"CLOSED_TASKS": "suljettu<br/>tehtävää", "CLOSED_TASKS": "suljettu<br/>tehtävää",
"IOCAINE_DOSES": "myrkkye-<br/>annosta", "IOCAINE_DOSES": "myrkkye-<br/>annosta",
"SHOW_STATISTICS_TITLE": "Näytä tilastot", "SHOW_STATISTICS_TITLE": "Näytä tilastot",
"TOGGLE_BAKLOG_GRAPH": "Show/Hide burndown graph" "TOGGLE_BAKLOG_GRAPH": "Show/Hide burndown graph",
"POINTS_PER_ROLE": "Points per role"
}, },
"SUMMARY": { "SUMMARY": {
"PROJECT_POINTS": "projekti<br/>pistettä", "PROJECT_POINTS": "projekti<br/>pistettä",
@ -1122,9 +1271,7 @@
"TITLE": "Suodattimet", "TITLE": "Suodattimet",
"REMOVE": "Poista suodattimet", "REMOVE": "Poista suodattimet",
"HIDE": "Piilota suodattimet", "HIDE": "Piilota suodattimet",
"SHOW": "Näytä suodattimet", "SHOW": "Näytä suodattimet"
"FILTER_CATEGORY_STATUS": "Tila",
"FILTER_CATEGORY_TAGS": "Avainsanat"
}, },
"SPRINTS": { "SPRINTS": {
"TITLE": "KIERROKSET", "TITLE": "KIERROKSET",
@ -1179,7 +1326,7 @@
"TASK": { "TASK": {
"PAGE_TITLE": "{{taskSubject}} - Task {{taskRef}} - {{projectName}}", "PAGE_TITLE": "{{taskSubject}} - Task {{taskRef}} - {{projectName}}",
"PAGE_DESCRIPTION": "Status: {{taskStatus }}. Description: {{taskDescription}}", "PAGE_DESCRIPTION": "Status: {{taskStatus }}. Description: {{taskDescription}}",
"SECTION_NAME": "Tehtävän tiedot", "SECTION_NAME": "Task",
"LINK_TASKBOARD": "Tehtävätaulu", "LINK_TASKBOARD": "Tehtävätaulu",
"TITLE_LINK_TASKBOARD": "Siirry tehtävätauluun", "TITLE_LINK_TASKBOARD": "Siirry tehtävätauluun",
"PLACEHOLDER_SUBJECT": "Anna tehtävän aihe", "PLACEHOLDER_SUBJECT": "Anna tehtävän aihe",
@ -1189,8 +1336,6 @@
"ORIGIN_US": "Tämä tehtävä on luotu", "ORIGIN_US": "Tämä tehtävä on luotu",
"TITLE_LINK_GO_ORIGIN": "Siirry käyttäjätarinaan", "TITLE_LINK_GO_ORIGIN": "Siirry käyttäjätarinaan",
"BLOCKED": "Tämä tehtävä on suljettu", "BLOCKED": "Tämä tehtävä on suljettu",
"PREVIOUS": "edellinen tehtävä",
"NEXT": "seuraava tehtävä",
"TITLE_DELETE_ACTION": "Poista tehtävä", "TITLE_DELETE_ACTION": "Poista tehtävä",
"LIGHTBOX_TITLE_BLOKING_TASK": "Estävä tehtävä", "LIGHTBOX_TITLE_BLOKING_TASK": "Estävä tehtävä",
"FIELDS": { "FIELDS": {
@ -1228,16 +1373,13 @@
"PAGE_TITLE": "Issues - {{projectName}}", "PAGE_TITLE": "Issues - {{projectName}}",
"PAGE_DESCRIPTION": "The issues list panel of the project {{projectName}}: {{projectDescription}}", "PAGE_DESCRIPTION": "The issues list panel of the project {{projectName}}: {{projectDescription}}",
"LIST_SECTION_NAME": "Pyynnöt", "LIST_SECTION_NAME": "Pyynnöt",
"SECTION_NAME": "Pyynnön tiedot", "SECTION_NAME": "Issue",
"ACTION_NEW_ISSUE": "+ UUSI PYYNTÖ", "ACTION_NEW_ISSUE": "+ UUSI PYYNTÖ",
"ACTION_PROMOTE_TO_US": "Liitä käyttäjätarinaan", "ACTION_PROMOTE_TO_US": "Liitä käyttäjätarinaan",
"PLACEHOLDER_FILTER_NAME": "Anna suodattimen nimi ja paina enter",
"PROMOTED": "Tämä pyyntö on liitetty Kthen:", "PROMOTED": "Tämä pyyntö on liitetty Kthen:",
"EXTERNAL_REFERENCE": "Tämä pyyntö on luotu täältä:", "EXTERNAL_REFERENCE": "Tämä pyyntö on luotu täältä:",
"GO_TO_EXTERNAL_REFERENCE": "Palaa alkuun", "GO_TO_EXTERNAL_REFERENCE": "Palaa alkuun",
"BLOCKED": "Tämä pyyntö on estetty", "BLOCKED": "Tämä pyyntö on estetty",
"TITLE_PREVIOUS_ISSUE": "edellinen pyyntö",
"TITLE_NEXT_ISSUE": "seuraava pyyntö",
"ACTION_DELETE": "Poista pyyntö", "ACTION_DELETE": "Poista pyyntö",
"LIGHTBOX_TITLE_BLOKING_ISSUE": "Estävä pyyntö", "LIGHTBOX_TITLE_BLOKING_ISSUE": "Estävä pyyntö",
"FIELDS": { "FIELDS": {
@ -1249,28 +1391,6 @@
"TITLE": "Liitä tämä pyyntö uuteen käyttäjätarinaan", "TITLE": "Liitä tämä pyyntö uuteen käyttäjätarinaan",
"MESSAGE": "Haluatko varmasti lisätä uuden käyttäjätarinan tästä pyynnöstä?" "MESSAGE": "Haluatko varmasti lisätä uuden käyttäjätarinan tästä pyynnöstä?"
}, },
"FILTERS": {
"TITLE": "Suodattimet",
"INPUT_SEARCH_PLACEHOLDER": "Otsikko tai viittaus",
"TITLE_ACTION_SEARCH": "Hae",
"ACTION_SAVE_CUSTOM_FILTER": "tallenna omaksi suodattimeksi",
"BREADCRUMB": "Suodattimet",
"TITLE_BREADCRUMB": "Suodattimet",
"CATEGORIES": {
"TYPE": "Tyyppi",
"STATUS": "Tila",
"SEVERITY": "Vakavuus",
"PRIORITIES": "Tärkeydet",
"TAGS": "Avainsanat",
"ASSIGNED_TO": "Tekijä",
"CREATED_BY": "Luoja",
"CUSTOM_FILTERS": "Omat suodattimet"
},
"CONFIRM_DELETE": {
"TITLE": "Poista oma suodatin",
"MESSAGE": "oma suodatin '{{customFilterName}}'"
}
},
"TABLE": { "TABLE": {
"COLUMNS": { "COLUMNS": {
"TYPE": "Tyyppi", "TYPE": "Tyyppi",
@ -1316,6 +1436,7 @@
"SEARCH": { "SEARCH": {
"PAGE_TITLE": "Search - {{projectName}}", "PAGE_TITLE": "Search - {{projectName}}",
"PAGE_DESCRIPTION": "Search anything, user stories, issues, tasks or wiki pages, in the project {{projectName}}: {{projectDescription}}", "PAGE_DESCRIPTION": "Search anything, user stories, issues, tasks or wiki pages, in the project {{projectName}}: {{projectDescription}}",
"FILTER_EPICS": "Epics",
"FILTER_USER_STORIES": "Käyttäjätarinat", "FILTER_USER_STORIES": "Käyttäjätarinat",
"FILTER_ISSUES": "Pyynnöt", "FILTER_ISSUES": "Pyynnöt",
"FILTER_TASKS": "Tehtävät", "FILTER_TASKS": "Tehtävät",
@ -1417,13 +1538,24 @@
"DELETE_LIGHTBOX_TITLE": "Poista wiki-sivu", "DELETE_LIGHTBOX_TITLE": "Poista wiki-sivu",
"DELETE_LINK_TITLE": "Delete Wiki link", "DELETE_LINK_TITLE": "Delete Wiki link",
"NAVIGATION": { "NAVIGATION": {
"SECTION_NAME": "Linkit", "HOME": "Main Page",
"ACTION_ADD_LINK": "Lisää linkki" "SECTION_NAME": "BOOKMARKS",
"ACTION_ADD_LINK": "Add bookmark",
"ALL_PAGES": "All wiki pages"
}, },
"SUMMARY": { "SUMMARY": {
"TIMES_EDITED": "kertaa<br/>muokattu", "TIMES_EDITED": "kertaa<br/>muokattu",
"LAST_EDIT": "viimeinen<br/>muokkaus", "LAST_EDIT": "viimeinen<br/>muokkaus",
"LAST_MODIFICATION": "viimeinen muokkaus" "LAST_MODIFICATION": "viimeinen muokkaus"
},
"SECTION_PAGES_LIST": "All pages",
"PAGES_LIST_COLUMNS": {
"TITLE": "Title",
"EDITIONS": "Editions",
"CREATED": "Luotu",
"MODIFIED": "Modified",
"CREATOR": "Creator",
"LAST_MODIFIER": "Last modifier"
} }
}, },
"HINTS": { "HINTS": {
@ -1447,6 +1579,8 @@
"TASK_CREATED_WITH_US": "{{username}} has created a new task {{obj_name}} in {{project_name}} which belongs to the US {{us_name}}", "TASK_CREATED_WITH_US": "{{username}} has created a new task {{obj_name}} in {{project_name}} which belongs to the US {{us_name}}",
"WIKI_CREATED": "{{username}} has created a new wiki page {{obj_name}} in {{project_name}}", "WIKI_CREATED": "{{username}} has created a new wiki page {{obj_name}} in {{project_name}}",
"MILESTONE_CREATED": "{{username}} has created a new sprint {{obj_name}} in {{project_name}}", "MILESTONE_CREATED": "{{username}} has created a new sprint {{obj_name}} in {{project_name}}",
"EPIC_CREATED": "{{username}} has created a new epic {{obj_name}} in {{project_name}}",
"EPIC_RELATED_USERSTORY_CREATED": "{{username}} has related the userstory {{related_us_name}} to the epic {{epic_name}} in {{project_name}}",
"NEW_PROJECT": "{{username}} created the project {{project_name}}", "NEW_PROJECT": "{{username}} created the project {{project_name}}",
"MILESTONE_UPDATED": "{{username}} has updated the sprint {{obj_name}}", "MILESTONE_UPDATED": "{{username}} has updated the sprint {{obj_name}}",
"US_UPDATED": "{{username}} has updated the attribute \"{{field_name}}\" of the US {{obj_name}}", "US_UPDATED": "{{username}} has updated the attribute \"{{field_name}}\" of the US {{obj_name}}",
@ -1459,9 +1593,13 @@
"TASK_UPDATED_WITH_US": "{{username}} has updated the attribute \"{{field_name}}\" of the task {{obj_name}} which belongs to the US {{us_name}}", "TASK_UPDATED_WITH_US": "{{username}} has updated the attribute \"{{field_name}}\" of the task {{obj_name}} which belongs to the US {{us_name}}",
"TASK_UPDATED_WITH_US_NEW_VALUE": "{{username}} has updated the attribute \"{{field_name}}\" of the task {{obj_name}} which belongs to the US {{us_name}} to {{new_value}}", "TASK_UPDATED_WITH_US_NEW_VALUE": "{{username}} has updated the attribute \"{{field_name}}\" of the task {{obj_name}} which belongs to the US {{us_name}} to {{new_value}}",
"WIKI_UPDATED": "{{username}} has updated the wiki page {{obj_name}}", "WIKI_UPDATED": "{{username}} has updated the wiki page {{obj_name}}",
"EPIC_UPDATED": "{{username}} has updated the attribute \"{{field_name}}\" of the epic {{obj_name}}",
"EPIC_UPDATED_WITH_NEW_VALUE": "{{username}} has updated the attribute \"{{field_name}}\" of the epic {{obj_name}} to {{new_value}}",
"EPIC_UPDATED_WITH_NEW_COLOR": "{{username}} has updated the \"{{field_name}}\" of the epic {{obj_name}} to <span class=\"new-color\" style=\"background: {{new_value}}\"></span>",
"NEW_COMMENT_US": "{{username}} has commented in the US {{obj_name}}", "NEW_COMMENT_US": "{{username}} has commented in the US {{obj_name}}",
"NEW_COMMENT_ISSUE": "{{username}} has commented in the issue {{obj_name}}", "NEW_COMMENT_ISSUE": "{{username}} has commented in the issue {{obj_name}}",
"NEW_COMMENT_TASK": "{{username}} has commented in the task {{obj_name}}", "NEW_COMMENT_TASK": "{{username}} has commented in the task {{obj_name}}",
"NEW_COMMENT_EPIC": "{{username}} has commented in the epic {{obj_name}}",
"NEW_MEMBER": "{{project_name}} has a new member", "NEW_MEMBER": "{{project_name}} has a new member",
"US_ADDED_MILESTONE": "{{username}} has added the US {{obj_name}} to {{sprint_name}}", "US_ADDED_MILESTONE": "{{username}} has added the US {{obj_name}} to {{sprint_name}}",
"US_MOVED": "{{username}} has moved the US {{obj_name}}", "US_MOVED": "{{username}} has moved the US {{obj_name}}",

View File

@ -35,6 +35,8 @@
"ONE_ITEM_LINE": "Un élément par ligne...", "ONE_ITEM_LINE": "Un élément par ligne...",
"NEW_BULK": "Nouvel ajout en bloc", "NEW_BULK": "Nouvel ajout en bloc",
"RELATED_TASKS": "Tâches associées", "RELATED_TASKS": "Tâches associées",
"PREVIOUS": "Précédent",
"NEXT": "Suivant",
"LOGOUT": "Déconnexion", "LOGOUT": "Déconnexion",
"EXTERNAL_USER": "un utilisateur externe", "EXTERNAL_USER": "un utilisateur externe",
"GENERIC_ERROR": "L'un de nos Oompa Loompas dit {{error}}.", "GENERIC_ERROR": "L'un de nos Oompa Loompas dit {{error}}.",
@ -43,8 +45,13 @@
"TEAM_REQUIREMENT": "Un besoin projet est un besoin qui est nécessaire au projet mais qui ne doit avoir aucun impact pour le client", "TEAM_REQUIREMENT": "Un besoin projet est un besoin qui est nécessaire au projet mais qui ne doit avoir aucun impact pour le client",
"OWNER": "Propriétaire du Projet", "OWNER": "Propriétaire du Projet",
"CAPSLOCK_WARNING": "Attention ! Vous utilisez des majuscules dans un champ qui est sensible à la casse.", "CAPSLOCK_WARNING": "Attention ! Vous utilisez des majuscules dans un champ qui est sensible à la casse.",
"CONFIRM_CLOSE_EDIT_MODE_TITLE": "Are you sure you want to close the edit mode?", "CONFIRM_CLOSE_EDIT_MODE_TITLE": "Êtes-vous sûr de vouloir fermer le mode Édition ?",
"CONFIRM_CLOSE_EDIT_MODE_MESSAGE": "Remember that if you close the edit mode without saving all the changes will be lost", "CONFIRM_CLOSE_EDIT_MODE_MESSAGE": "Souvenez-vous que si vous fermez le mode édition sans enregistrer, toutes vos modifications seront perdues",
"RELATED_USERSTORIES": "Related user stories",
"CARD": {
"ASSIGN_TO": "Affecter à",
"EDIT": "Modifier la carte"
},
"FORM_ERRORS": { "FORM_ERRORS": {
"DEFAULT_MESSAGE": "Cette valeur semble être invalide.", "DEFAULT_MESSAGE": "Cette valeur semble être invalide.",
"TYPE_EMAIL": "Cette valeur devrait être une adresse courriel valide.", "TYPE_EMAIL": "Cette valeur devrait être une adresse courriel valide.",
@ -115,8 +122,9 @@
"USER_STORY": "Récit utilisateur", "USER_STORY": "Récit utilisateur",
"TASK": "Tâche", "TASK": "Tâche",
"ISSUE": "Ticket", "ISSUE": "Ticket",
"EPIC": "Épopée",
"TAGS": { "TAGS": {
"PLACEHOLDER": "Taggez moi !", "PLACEHOLDER": "Enter tag",
"DELETE": "Supprimer le mot-clé", "DELETE": "Supprimer le mot-clé",
"ADD": "Ajouter un mot-clé" "ADD": "Ajouter un mot-clé"
}, },
@ -193,12 +201,29 @@
"CONFIRM_DELETE": "Souvenez-vous que toutes les valeurs de ce champ personnalisé vont être effacées.\nEtes-vous sûr de vouloir continuer ?" "CONFIRM_DELETE": "Souvenez-vous que toutes les valeurs de ce champ personnalisé vont être effacées.\nEtes-vous sûr de vouloir continuer ?"
}, },
"FILTERS": { "FILTERS": {
"TITLE": "filtres", "TITLE": "Filtres",
"INPUT_PLACEHOLDER": "Objet ou référence", "INPUT_PLACEHOLDER": "Objet ou référence",
"TITLE_ACTION_FILTER_BUTTON": "recherche", "TITLE_ACTION_FILTER_BUTTON": "recherche",
"BREADCRUMB_TITLE": "retour aux catégories", "INPUT_SEARCH_PLACEHOLDER": "Objet ou réf.",
"BREADCRUMB_FILTERS": "Filtres", "TITLE_ACTION_SEARCH": "Rechercher",
"BREADCRUMB_STATUS": "état" "ACTION_SAVE_CUSTOM_FILTER": "sauvegarder en tant que filtre personnalisé",
"PLACEHOLDER_FILTER_NAME": "Écrivez le nom du filtre et appuyez sur \"Entrée\"",
"APPLIED_FILTERS_NUM": "filters applied",
"CATEGORIES": {
"TYPE": "Type",
"STATUS": "Statut",
"SEVERITY": "Gravité",
"PRIORITIES": "Priorités",
"TAGS": "Mots-clés",
"ASSIGNED_TO": "Affecté à",
"CREATED_BY": "Créé par",
"CUSTOM_FILTERS": "Filtres personnalisés",
"EPIC": "Épopée"
},
"CONFIRM_DELETE": {
"TITLE": "Supprime le filtre personnalisé",
"MESSAGE": "le filtre personnalisé '{{customFilterName}}'"
}
}, },
"WYSIWYG": { "WYSIWYG": {
"H1_BUTTON": "Premier niveau de titre", "H1_BUTTON": "Premier niveau de titre",
@ -227,10 +252,19 @@
"CODE_BLOCK_SAMPLE_TEXT": "Votre texte ici…", "CODE_BLOCK_SAMPLE_TEXT": "Votre texte ici…",
"PREVIEW_BUTTON": "Aperçu", "PREVIEW_BUTTON": "Aperçu",
"EDIT_BUTTON": "Modifier", "EDIT_BUTTON": "Modifier",
"ATTACH_FILE_HELP": "Attach files by dragging & dropping on the textarea above.", "ATTACH_FILE_HELP": "Joindre des fichiers en glissant et déposant ceux-ci sur la zone de texte ci-dessus.",
"ATTACH_FILE_HELP_SAVE_FIRST": "Enregistrez d'abord si vous voulez joindre des fichiers en glissant et déposant ceux-ci sur la zone de texte ci-dessus.",
"MARKDOWN_HELP": "Aide sur la syntaxe Markdown" "MARKDOWN_HELP": "Aide sur la syntaxe Markdown"
}, },
"PERMISIONS_CATEGORIES": { "PERMISIONS_CATEGORIES": {
"EPICS": {
"NAME": "Épopées",
"VIEW_EPICS": "View epics",
"ADD_EPICS": "Add epics",
"MODIFY_EPICS": "Modify epics",
"COMMENT_EPICS": "Comment epics",
"DELETE_EPICS": "Delete epics"
},
"SPRINTS": { "SPRINTS": {
"NAME": "Sprints", "NAME": "Sprints",
"VIEW_SPRINTS": "Voir les sprints", "VIEW_SPRINTS": "Voir les sprints",
@ -243,6 +277,7 @@
"VIEW_USER_STORIES": "Afficher les récits utilisateur", "VIEW_USER_STORIES": "Afficher les récits utilisateur",
"ADD_USER_STORIES": "Ajouter des récits utilisateur", "ADD_USER_STORIES": "Ajouter des récits utilisateur",
"MODIFY_USER_STORIES": "Modifier les récits utilisateur", "MODIFY_USER_STORIES": "Modifier les récits utilisateur",
"COMMENT_USER_STORIES": "Commenter les histoires utilisateur",
"DELETE_USER_STORIES": "Supprimer des récits utilisateur" "DELETE_USER_STORIES": "Supprimer des récits utilisateur"
}, },
"TASKS": { "TASKS": {
@ -250,6 +285,7 @@
"VIEW_TASKS": "Voir les tâches", "VIEW_TASKS": "Voir les tâches",
"ADD_TASKS": "Ajouter des tâches", "ADD_TASKS": "Ajouter des tâches",
"MODIFY_TASKS": "Modifier des tâches", "MODIFY_TASKS": "Modifier des tâches",
"COMMENT_TASKS": "Commenter les tâches",
"DELETE_TASKS": "Supprimer des tâches" "DELETE_TASKS": "Supprimer des tâches"
}, },
"ISSUES": { "ISSUES": {
@ -257,6 +293,7 @@
"VIEW_ISSUES": "Voir les tickets", "VIEW_ISSUES": "Voir les tickets",
"ADD_ISSUES": "Ajouter des tickets", "ADD_ISSUES": "Ajouter des tickets",
"MODIFY_ISSUES": "Modifier des tickets", "MODIFY_ISSUES": "Modifier des tickets",
"COMMENT_ISSUES": "Commenter les tickets",
"DELETE_ISSUES": "Supprimer des tickets" "DELETE_ISSUES": "Supprimer des tickets"
}, },
"WIKI": { "WIKI": {
@ -366,6 +403,41 @@
"WATCHING_SECTION": "Suivi", "WATCHING_SECTION": "Suivi",
"DASHBOARD": "Tableau de bord des projets" "DASHBOARD": "Tableau de bord des projets"
}, },
"EPICS": {
"TITLE": "ÉPOPÉES",
"SECTION_NAME": "Épopées",
"EPIC": "ÉPOPÉE",
"PAGE_TITLE": "Epics - {{projectName}}",
"PAGE_DESCRIPTION": "The epics list of the project {{projectName}}: {{projectDescription}}",
"DASHBOARD": {
"ADD": "+ AJOUTER ÉPOPÉE",
"UNASSIGNED": "Non affecté"
},
"EMPTY": {
"TITLE": "It looks like there aren't any epics yet",
"EXPLANATION": "Epics are items at a higher level that encompass user stories.<br />Epics are at the top of the hierarchy and can be used to group user stories together.",
"HELP": "En savoir plus sur les épopées"
},
"TABLE": {
"VOTES": "Votes",
"NAME": "Nom",
"PROJECT": "Projet",
"SPRINT": "Sprint",
"ASSIGNED_TO": "Affecté",
"STATUS": "Statut",
"PROGRESS": "Avancement",
"VIEW_OPTIONS": "Voir les options"
},
"CREATE": {
"TITLE": "Nouvelle épopée",
"PLACEHOLDER_DESCRIPTION": "Please add descriptive text to help others better understand this epic",
"TEAM_REQUIREMENT": "Besoin projet",
"CLIENT_REQUIREMENT": "Besoin client",
"BLOCKED": "Bloqué",
"BLOCKED_NOTE_PLACEHOLDER": "Pourquoi cette épopée est-elle bloquée ?",
"CREATE_EPIC": "Créer une épopée"
}
},
"PROJECTS": { "PROJECTS": {
"PAGE_TITLE": "Mes projets - Taiga", "PAGE_TITLE": "Mes projets - Taiga",
"PAGE_DESCRIPTION": "Une liste de tous vos projets, vous pouvez la trier ou en créer une nouvelle.", "PAGE_DESCRIPTION": "Une liste de tous vos projets, vous pouvez la trier ou en créer une nouvelle.",
@ -402,7 +474,8 @@
"ADMIN": { "ADMIN": {
"COMMON": { "COMMON": {
"TITLE_ACTION_EDIT_VALUE": "Modifier la valeur", "TITLE_ACTION_EDIT_VALUE": "Modifier la valeur",
"TITLE_ACTION_DELETE_VALUE": "Supprimer" "TITLE_ACTION_DELETE_VALUE": "Supprimer",
"TITLE_ACTION_DELETE_TAG": "Supprimer le mot-clé"
}, },
"HELP": "Avez-vous besoin d'aide ? Consultez notre page d'assistance !", "HELP": "Avez-vous besoin d'aide ? Consultez notre page d'assistance !",
"PROJECT_DEFAULT_VALUES": { "PROJECT_DEFAULT_VALUES": {
@ -435,6 +508,8 @@
"TITLE": "Modules", "TITLE": "Modules",
"ENABLE": "Activer", "ENABLE": "Activer",
"DISABLE": "Désactiver", "DISABLE": "Désactiver",
"EPICS": "Épopées",
"EPICS_DESCRIPTION": "Visualiser et gérer les aspects les plus stratégiques de votre projet",
"BACKLOG": "Backlog", "BACKLOG": "Backlog",
"BACKLOG_DESCRIPTION": "Gérez votre récits utilisateur pour garder une vue organisée des travaux à venir et priorisés.", "BACKLOG_DESCRIPTION": "Gérez votre récits utilisateur pour garder une vue organisée des travaux à venir et priorisés.",
"NUMBER_SPRINTS": "Nombre prévu de sprints", "NUMBER_SPRINTS": "Nombre prévu de sprints",
@ -497,6 +572,7 @@
"REGENERATE_SUBTITLE": "Vous êtes sur le point de changer l'url d'accès aux données CSV. L'url précédente sera désactivée. Êtes-vous sûr ?" "REGENERATE_SUBTITLE": "Vous êtes sur le point de changer l'url d'accès aux données CSV. L'url précédente sera désactivée. Êtes-vous sûr ?"
}, },
"CSV": { "CSV": {
"SECTION_TITLE_EPIC": "epics reports",
"SECTION_TITLE_US": "rapports des récits utilisateur", "SECTION_TITLE_US": "rapports des récits utilisateur",
"SECTION_TITLE_TASK": "rapports des tâches", "SECTION_TITLE_TASK": "rapports des tâches",
"SECTION_TITLE_ISSUE": "Rapports des tickets", "SECTION_TITLE_ISSUE": "Rapports des tickets",
@ -509,6 +585,8 @@
"CUSTOM_FIELDS": { "CUSTOM_FIELDS": {
"TITLE": "Champs personnalisés", "TITLE": "Champs personnalisés",
"SUBTITLE": "Spécifiez les champs personnalisés de vos récits utilisateur, tâches et tickets", "SUBTITLE": "Spécifiez les champs personnalisés de vos récits utilisateur, tâches et tickets",
"EPIC_DESCRIPTION": "Epics custom fields",
"EPIC_ADD": "Add a custom field in epics",
"US_DESCRIPTION": "Champs personnalisés des récits utilisateur", "US_DESCRIPTION": "Champs personnalisés des récits utilisateur",
"US_ADD": "Ajouter un champ personnalisé dans les récits utilisateur", "US_ADD": "Ajouter un champ personnalisé dans les récits utilisateur",
"TASK_DESCRIPTION": "Champs personnalisés de tâches", "TASK_DESCRIPTION": "Champs personnalisés de tâches",
@ -546,7 +624,8 @@
"PROJECT_VALUES_STATUS": { "PROJECT_VALUES_STATUS": {
"TITLE": "Statut", "TITLE": "Statut",
"SUBTITLE": "Spécifiez les statuts que vont prendre vos récits utilisateur, tâches et tickets", "SUBTITLE": "Spécifiez les statuts que vont prendre vos récits utilisateur, tâches et tickets",
"US_TITLE": "Statuts des RU", "EPIC_TITLE": "Epic Statuses",
"US_TITLE": "User Story Statuses",
"TASK_TITLE": "Statuts des tâches", "TASK_TITLE": "Statuts des tâches",
"ISSUE_TITLE": "Statuts des Tickets" "ISSUE_TITLE": "Statuts des Tickets"
}, },
@ -556,6 +635,17 @@
"ISSUE_TITLE": "Types de tickets", "ISSUE_TITLE": "Types de tickets",
"ACTION_ADD": "Ajouter un nouveau {{objName}}" "ACTION_ADD": "Ajouter un nouveau {{objName}}"
}, },
"PROJECT_VALUES_TAGS": {
"TITLE": "Mots-clés",
"SUBTITLE": "Voir et modifier la couleur de vos mots-clés",
"EMPTY": "Il n'y a pas de mots-clés pour l'instant",
"EMPTY_SEARCH": "Il semble qu'aucun résultat ne correspond à vos critères de recherche",
"ACTION_ADD": "Ajouter un mot-clé",
"NEW_TAG": "Nouveau mot-clé",
"MIXING_HELP_TEXT": "Sélectionnez les mots-clés que vous voulez fusionner",
"MIXING_MERGE": "Fusionner des mots-clés",
"SELECTED": "Sélectionné"
},
"ROLES": { "ROLES": {
"PAGE_TITLE": "Rôles - {{projectName}}", "PAGE_TITLE": "Rôles - {{projectName}}",
"WARNING_NO_ROLE": "Attention, aucun rôle dans votre projet ne pourra estimer la valeur du point pour les récits utilisateurs", "WARNING_NO_ROLE": "Attention, aucun rôle dans votre projet ne pourra estimer la valeur du point pour les récits utilisateurs",
@ -588,6 +678,10 @@
"SECTION_NAME": "Github", "SECTION_NAME": "Github",
"PAGE_TITLE": "Github - {{projectName}}" "PAGE_TITLE": "Github - {{projectName}}"
}, },
"GOGS": {
"SECTION_NAME": "Gogs",
"PAGE_TITLE": "Gogs - {{projectName}}"
},
"WEBHOOKS": { "WEBHOOKS": {
"PAGE_TITLE": "Webhooks - {{projectName}}", "PAGE_TITLE": "Webhooks - {{projectName}}",
"SECTION_NAME": "Webhooks", "SECTION_NAME": "Webhooks",
@ -643,13 +737,14 @@
"DEFAULT_DELETE_MESSAGE": "l'invitation à {{email}}" "DEFAULT_DELETE_MESSAGE": "l'invitation à {{email}}"
}, },
"DEFAULT_VALUES": { "DEFAULT_VALUES": {
"LABEL_EPIC_STATUS": "Default value for epic status selector",
"LABEL_US_STATUS": "Default value for user story status selector",
"LABEL_POINTS": "Valeur par défaut pour la sélection des points", "LABEL_POINTS": "Valeur par défaut pour la sélection des points",
"LABEL_US": "Valeur par défaut pour la sélection du récit utilisateur",
"LABEL_TASK_STATUS": "Valeur par défaut pour la sélection de l'état des tâches", "LABEL_TASK_STATUS": "Valeur par défaut pour la sélection de l'état des tâches",
"LABEL_PRIORITY": "Valeur par défaut de la sélection des priorités",
"LABEL_SEVERITY": "Valeur par défaut pour le sélecteur de gravité",
"LABEL_ISSUE_TYPE": "Valeur par défaut pour le sélecteur de type", "LABEL_ISSUE_TYPE": "Valeur par défaut pour le sélecteur de type",
"LABEL_ISSUE_STATUS": "Valeur par défaut pour le sélecteur de statut de bug" "LABEL_ISSUE_STATUS": "Valeur par défaut pour le sélecteur de statut de bug",
"LABEL_PRIORITY": "Valeur par défaut de la sélection des priorités",
"LABEL_SEVERITY": "Valeur par défaut pour le sélecteur de gravité"
}, },
"STATUS": { "STATUS": {
"PLACEHOLDER_WRITE_STATUS_NAME": "Entrez le nom du nouvel état" "PLACEHOLDER_WRITE_STATUS_NAME": "Entrez le nom du nouvel état"
@ -681,7 +776,8 @@
"PRIORITIES": "Priorités", "PRIORITIES": "Priorités",
"SEVERITIES": "Gravité", "SEVERITIES": "Gravité",
"TYPES": "Types", "TYPES": "Types",
"CUSTOM_FIELDS": "Champs personnalisés" "CUSTOM_FIELDS": "Champs personnalisés",
"TAGS": "Mots-clés"
}, },
"SUBMENU_PROJECT_PROFILE": { "SUBMENU_PROJECT_PROFILE": {
"TITLE": "Profil projet" "TITLE": "Profil projet"
@ -751,6 +847,8 @@
"FILTER_TYPE_ALL_TITLE": "Voir tous", "FILTER_TYPE_ALL_TITLE": "Voir tous",
"FILTER_TYPE_PROJECTS": "Projets", "FILTER_TYPE_PROJECTS": "Projets",
"FILTER_TYPE_PROJECT_TITLES": "Voir uniquement les projets", "FILTER_TYPE_PROJECT_TITLES": "Voir uniquement les projets",
"FILTER_TYPE_EPICS": "Épopées",
"FILTER_TYPE_EPIC_TITLES": "Show only epics",
"FILTER_TYPE_USER_STORIES": "Récits", "FILTER_TYPE_USER_STORIES": "Récits",
"FILTER_TYPE_USER_STORIES_TITLES": "Voir uniquement les user stories", "FILTER_TYPE_USER_STORIES_TITLES": "Voir uniquement les user stories",
"FILTER_TYPE_TASKS": "Tâches", "FILTER_TYPE_TASKS": "Tâches",
@ -950,8 +1048,8 @@
"CREATE_MEMBER": { "CREATE_MEMBER": {
"PLACEHOLDER_INVITATION_TEXT": "(Optionnel) Ajoutez un texte personnalisé à l'invitation. Dites quelque chose de gentil à vos nouveaux membres ;-)", "PLACEHOLDER_INVITATION_TEXT": "(Optionnel) Ajoutez un texte personnalisé à l'invitation. Dites quelque chose de gentil à vos nouveaux membres ;-)",
"PLACEHOLDER_TYPE_EMAIL": "Saisissez une adresse courriel", "PLACEHOLDER_TYPE_EMAIL": "Saisissez une adresse courriel",
"LIMIT_USERS_WARNING_MESSAGE_FOR_OWNER": "Désolé, ce projet ne peut avoir plus de <strong>{{maxMembers}}</strong> membres. <br>Si vous désirez augmenter cette limite, merci de contacter l'administrateur.", "LIMIT_USERS_WARNING_MESSAGE_FOR_OWNER": "You are about to reach the maximum number of members allowed for this project, <strong>{{maxMembers}}</strong> members. If you would like to increase the current limit, please contact the administrator.",
"LIMIT_USERS_WARNING_MESSAGE": "Désolé, ce projet ne peut avoir plus de <strong>{{maxMembers}}</strong> membres." "LIMIT_USERS_WARNING_MESSAGE": "You are about to reach the maximum number of members allowed for this project, <strong>{{maxMembers}}</strong> members."
}, },
"LEAVE_PROJECT_WARNING": { "LEAVE_PROJECT_WARNING": {
"TITLE": "Malheureusement, ce projet ne peut pas être laissé sans propriétaire", "TITLE": "Malheureusement, ce projet ne peut pas être laissé sans propriétaire",
@ -970,10 +1068,30 @@
"BUTTON": "Demander à ce membre du projet de devenir le nouveau propriétaire" "BUTTON": "Demander à ce membre du projet de devenir le nouveau propriétaire"
} }
}, },
"EPIC": {
"PAGE_TITLE": "{{epicSubject}} - Epic {{epicRef}} - {{projectName}}",
"PAGE_DESCRIPTION": "Status: {{epicStatus }}. Description: {{epicDescription}}",
"SECTION_NAME": "Épopée",
"TITLE_LIGHTBOX_UNLINK_RELATED_USERSTORY": "Unlink related userstory",
"MSG_LIGHTBOX_UNLINK_RELATED_USERSTORY": "It will delete the link to the related userstory '{{subject}}'",
"ERROR_UNLINK_RELATED_USERSTORY": "We have not been able to unlink: {{errorMessage}}",
"CREATE_RELATED_USERSTORIES": "Create a relationship with",
"NEW_USERSTORY": "Nouveau récit utilisateur",
"EXISTING_USERSTORY": "Existing user story",
"CHOOSE_PROJECT_FOR_CREATION": "What's the project?",
"SUBJECT": "Objet",
"SUBJECT_BULK_MODE": "Subject (bulk insert)",
"CHOOSE_PROJECT_FROM": "What's the project?",
"CHOOSE_USERSTORY": "What's the user story?",
"NO_USERSTORIES": "This project has no User Stories yet. Please select another project.",
"FILTER_USERSTORIES": "Filter user stories",
"LIGHTBOX_TITLE_BLOKING_EPIC": "Blocking epic",
"ACTION_DELETE": "Delete epic"
},
"US": { "US": {
"PAGE_TITLE": "{{userStorySubject}} - Récit utilisateur {{userStoryRef}} - {{projectName}}", "PAGE_TITLE": "{{userStorySubject}} - Récit utilisateur {{userStoryRef}} - {{projectName}}",
"PAGE_DESCRIPTION": "État : {{userStoryStatus }}. Achevé {{userStoryProgressPercentage}}% ({{userStoryClosedTasks}} sur {{userStoryTotalTasks}} tâches fermées). Points : {{userStoryPoints}}. Description : {{userStoryDescription}}", "PAGE_DESCRIPTION": "État : {{userStoryStatus }}. Achevé {{userStoryProgressPercentage}}% ({{userStoryClosedTasks}} sur {{userStoryTotalTasks}} tâches fermées). Points : {{userStoryPoints}}. Description : {{userStoryDescription}}",
"SECTION_NAME": "Détails du récit utilisateur", "SECTION_NAME": "Récit utilisateur",
"LINK_TASKBOARD": "Tableau des tâches", "LINK_TASKBOARD": "Tableau des tâches",
"TITLE_LINK_TASKBOARD": "Aller au tableau des tâches", "TITLE_LINK_TASKBOARD": "Aller au tableau des tâches",
"TOTAL_POINTS": "total des points", "TOTAL_POINTS": "total des points",
@ -984,14 +1102,23 @@
"EXTERNAL_REFERENCE": "Ce récit utilisateur a été créé depuis", "EXTERNAL_REFERENCE": "Ce récit utilisateur a été créé depuis",
"GO_TO_EXTERNAL_REFERENCE": "Allez à l'origine", "GO_TO_EXTERNAL_REFERENCE": "Allez à l'origine",
"BLOCKED": "Ce récit utilisateur est bloqué", "BLOCKED": "Ce récit utilisateur est bloqué",
"PREVIOUS": "récit utilisateur précédent",
"NEXT": "récit utilisateur suivant",
"TITLE_DELETE_ACTION": "Supprimer le récit utilisateur", "TITLE_DELETE_ACTION": "Supprimer le récit utilisateur",
"LIGHTBOX_TITLE_BLOKING_US": "Bloque le RU", "LIGHTBOX_TITLE_BLOKING_US": "Bloque le RU",
"TASK_COMPLETED": "{{totalClosedTasks}}/{{totalTasks}} tâches complétées", "TASK_COMPLETED": "{{totalClosedTasks}}/{{totalTasks}} tâches complétées",
"ASSIGN": "Affecter le récit utilisateur", "ASSIGN": "Affecter le récit utilisateur",
"NOT_ESTIMATED": "Non estimé", "NOT_ESTIMATED": "Non estimé",
"TOTAL_US_POINTS": "Total des points RU", "TOTAL_US_POINTS": "Total des points RU",
"TRIBE": {
"PUBLISH": "Publish as Gig in Taiga Tribe",
"PUBLISH_INFO": "Plus d'informations",
"PUBLISH_TITLE": "More info on publishing in Taiga Tribe",
"PUBLISHED_AS_GIG": "Story published as Gig in Taiga Tribe",
"EDIT_LINK": "Modifier le lien",
"CLOSE": "Fermer",
"SYNCHRONIZE_LINK": "synchronize with Taiga Tribe",
"PUBLISH_MORE_INFO_TITLE": "Avez-vous besoin de quelqu'un pour cette tâche ?",
"PUBLISH_MORE_INFO_TEXT": "<p>If you need help with a particular piece of work you can easily create gigs on<a href='taigatribe.com' title='Taiga Tribe'> Taiga Tribe </a> and receive help from all over the world. You will be able to control and manage the gig enjoying a great community eager to contribute.</p><p><a href='taigatribe.com' title='Taiga Tribe'> TaigaTribe </a> was born as a Taiga sibling. Both platforms can live separately but we believe that there is much power in using them combined so we are making sure the integration works like a charm.</p>"
},
"FIELDS": { "FIELDS": {
"TEAM_REQUIREMENT": "Besoin projet", "TEAM_REQUIREMENT": "Besoin projet",
"CLIENT_REQUIREMENT": "Besoin client", "CLIENT_REQUIREMENT": "Besoin client",
@ -999,28 +1126,47 @@
} }
}, },
"COMMENTS": { "COMMENTS": {
"DELETED_INFO": "Commentaire supprimé par {{user}} le {{date}}", "DELETED_INFO": "Commentaire supprimé par {{user}}",
"TITLE": "Commentaires", "TITLE": "Commentaires",
"COMMENTS_COUNT": "{{comments}} commentaires",
"ORDER": "Trier",
"OLDER_FIRST": "Plus ancien d'abord",
"RECENT_FIRST": "Plus récent d'abord",
"COMMENT": "Commentaire", "COMMENT": "Commentaire",
"EDIT_COMMENT": "Modifier le commentaire",
"EDITED_COMMENT": "Modifié :",
"SHOW_HISTORY": "Voir l'historique",
"TYPE_NEW_COMMENT": "Entrez un nouveau commentaire ici", "TYPE_NEW_COMMENT": "Entrez un nouveau commentaire ici",
"SHOW_DELETED": "Afficher le commentaire supprimé", "SHOW_DELETED": "Afficher le commentaire supprimé",
"HIDE_DELETED": "Cacher le commentaire supprimé", "HIDE_DELETED": "Cacher le commentaire supprimé",
"DELETE": "Supprimer le commentaire", "DELETE": "Supprimer le commentaire",
"RESTORE": "Restaurer le commentaire" "RESTORE": "Restaurer le commentaire",
"HISTORY": {
"TITLE": "Activité"
}
}, },
"ACTIVITY": { "ACTIVITY": {
"SHOW_ACTIVITY": "Afficher l'activité", "SHOW_ACTIVITY": "Afficher l'activité",
"DATETIME": "DD MMM YYYY HH:mm", "DATETIME": "DD MMM YYYY HH:mm",
"SHOW_MORE": "+ Montrer les entrées précédentes ({{showMore}} plus)", "SHOW_MORE": "+ Montrer les entrées précédentes ({{showMore}} plus)",
"TITLE": "Activité", "TITLE": "Activité",
"ACTIVITIES_COUNT": "{{activities}} activités",
"REMOVED": "supprimé", "REMOVED": "supprimé",
"ADDED": "ajouté", "ADDED": "ajouté",
"US_POINTS": "Points du récit utilisateur ({{name}})", "TAGS_ADDED": "Mots-clés ajoutés :",
"NEW_ATTACHMENT": "nouvelle pièce jointe", "TAGS_REMOVED": "Mots-clés supprimés",
"DELETED_ATTACHMENT": "Pièce jointe supprimée", "US_POINTS": "{{role}} points",
"UPDATED_ATTACHMENT": "Pièce jointe {{filename}} modifiée", "NEW_ATTACHMENT": "Nouvelle pièce jointe",
"DELETED_CUSTOM_ATTRIBUTE": "Attribut personnalisé supprimé", "DELETED_ATTACHMENT": "Pièces jointes supprimées :",
"UPDATED_ATTACHMENT": "Pièces jointes mises à jour ({{filename}}) :",
"CREATED_CUSTOM_ATTRIBUTE": "Attribut personnalisé créé",
"UPDATED_CUSTOM_ATTRIBUTE": "Attribut personnalisé mis à jour",
"SIZE_CHANGE": "A fait {size, plural, one{une modification} other{# modifications}}", "SIZE_CHANGE": "A fait {size, plural, one{une modification} other{# modifications}}",
"BECAME_DEPRECATED": "devenu obsolète",
"BECAME_UNDEPRECATED": "n'est plus obsolète",
"TEAM_REQUIREMENT": "Besoin projet",
"CLIENT_REQUIREMENT": "Besoin client",
"BLOCKED": "Bloqué",
"VALUES": { "VALUES": {
"YES": "oui", "YES": "oui",
"NO": "no", "NO": "no",
@ -1052,12 +1198,14 @@
"TAGS": "mots-clés", "TAGS": "mots-clés",
"ATTACHMENTS": "pièces jointes", "ATTACHMENTS": "pièces jointes",
"IS_DEPRECATED": "est obsolète", "IS_DEPRECATED": "est obsolète",
"IS_NOT_DEPRECATED": "n'est pas obsolète",
"ORDER": "classement", "ORDER": "classement",
"BACKLOG_ORDER": "classement du backlog", "BACKLOG_ORDER": "classement du backlog",
"SPRINT_ORDER": "classement du sprint", "SPRINT_ORDER": "classement du sprint",
"KANBAN_ORDER": "Classement du Kanban", "KANBAN_ORDER": "Classement du Kanban",
"TASKBOARD_ORDER": "trier le tableau des tâches", "TASKBOARD_ORDER": "trier le tableau des tâches",
"US_ORDER": "classement des récits utilisateur" "US_ORDER": "classement des récits utilisateur",
"COLOR": "couleur"
} }
}, },
"BACKLOG": { "BACKLOG": {
@ -1109,7 +1257,8 @@
"CLOSED_TASKS": "tâches<br />fermées", "CLOSED_TASKS": "tâches<br />fermées",
"IOCAINE_DOSES": "doses<br />de iocaine", "IOCAINE_DOSES": "doses<br />de iocaine",
"SHOW_STATISTICS_TITLE": "Afficher les statistiques", "SHOW_STATISTICS_TITLE": "Afficher les statistiques",
"TOGGLE_BAKLOG_GRAPH": "Afficher/masquer le graphique d'avancement" "TOGGLE_BAKLOG_GRAPH": "Afficher/masquer le graphique d'avancement",
"POINTS_PER_ROLE": "Points par rôle"
}, },
"SUMMARY": { "SUMMARY": {
"PROJECT_POINTS": "projet<br />points", "PROJECT_POINTS": "projet<br />points",
@ -1122,9 +1271,7 @@
"TITLE": "Filtres", "TITLE": "Filtres",
"REMOVE": "Supprimer les filtres", "REMOVE": "Supprimer les filtres",
"HIDE": "Cacher les filtres", "HIDE": "Cacher les filtres",
"SHOW": "Afficher les filtres", "SHOW": "Afficher les filtres"
"FILTER_CATEGORY_STATUS": "Etat",
"FILTER_CATEGORY_TAGS": "Mots-clés"
}, },
"SPRINTS": { "SPRINTS": {
"TITLE": "SPRINTS", "TITLE": "SPRINTS",
@ -1179,7 +1326,7 @@
"TASK": { "TASK": {
"PAGE_TITLE": "{{taskSubject}} - Tâche {{taskRef}} - {{projectName}}", "PAGE_TITLE": "{{taskSubject}} - Tâche {{taskRef}} - {{projectName}}",
"PAGE_DESCRIPTION": "État : {{taskStatus }}. Description : {{taskDescription}}", "PAGE_DESCRIPTION": "État : {{taskStatus }}. Description : {{taskDescription}}",
"SECTION_NAME": "Détails de la tâche", "SECTION_NAME": "Tâche",
"LINK_TASKBOARD": "Tableau des tâches", "LINK_TASKBOARD": "Tableau des tâches",
"TITLE_LINK_TASKBOARD": "Aller au tableau des tâches", "TITLE_LINK_TASKBOARD": "Aller au tableau des tâches",
"PLACEHOLDER_SUBJECT": "Entrez l'objet de la nouvelle tâche", "PLACEHOLDER_SUBJECT": "Entrez l'objet de la nouvelle tâche",
@ -1189,8 +1336,6 @@
"ORIGIN_US": "Cette tâche a été créée par", "ORIGIN_US": "Cette tâche a été créée par",
"TITLE_LINK_GO_ORIGIN": "Aller au récit utilisateur", "TITLE_LINK_GO_ORIGIN": "Aller au récit utilisateur",
"BLOCKED": "Cette tâche est bloquée", "BLOCKED": "Cette tâche est bloquée",
"PREVIOUS": "tâche précédente",
"NEXT": "tâche suivante",
"TITLE_DELETE_ACTION": "Supprimer une tâche", "TITLE_DELETE_ACTION": "Supprimer une tâche",
"LIGHTBOX_TITLE_BLOKING_TASK": "Tâche bloquante", "LIGHTBOX_TITLE_BLOKING_TASK": "Tâche bloquante",
"FIELDS": { "FIELDS": {
@ -1228,16 +1373,13 @@
"PAGE_TITLE": "Tickets - {{projectName}}", "PAGE_TITLE": "Tickets - {{projectName}}",
"PAGE_DESCRIPTION": "Le panneau de la liste des tickets du projet {{projectName}} : {{projectDescription}}", "PAGE_DESCRIPTION": "Le panneau de la liste des tickets du projet {{projectName}} : {{projectDescription}}",
"LIST_SECTION_NAME": "Tickets", "LIST_SECTION_NAME": "Tickets",
"SECTION_NAME": "Détails du ticket", "SECTION_NAME": "Ticket",
"ACTION_NEW_ISSUE": "+ NOUVEAU TICKET", "ACTION_NEW_ISSUE": "+ NOUVEAU TICKET",
"ACTION_PROMOTE_TO_US": "Promouvoir en récit utilisateur", "ACTION_PROMOTE_TO_US": "Promouvoir en récit utilisateur",
"PLACEHOLDER_FILTER_NAME": "Écrivez le nom du filtre et appuyez sur \"Entrée\"",
"PROMOTED": "Le ticket a été promu en récit utilisateur", "PROMOTED": "Le ticket a été promu en récit utilisateur",
"EXTERNAL_REFERENCE": "Ce ticket a été créé à partir de", "EXTERNAL_REFERENCE": "Ce ticket a été créé à partir de",
"GO_TO_EXTERNAL_REFERENCE": "Aller à l'origine", "GO_TO_EXTERNAL_REFERENCE": "Aller à l'origine",
"BLOCKED": "Ce bug est bloqué", "BLOCKED": "Ce bug est bloqué",
"TITLE_PREVIOUS_ISSUE": "ticket précédent",
"TITLE_NEXT_ISSUE": "ticket suivant",
"ACTION_DELETE": "Supprimer le ticket", "ACTION_DELETE": "Supprimer le ticket",
"LIGHTBOX_TITLE_BLOKING_ISSUE": "Ticket bloquant", "LIGHTBOX_TITLE_BLOKING_ISSUE": "Ticket bloquant",
"FIELDS": { "FIELDS": {
@ -1249,28 +1391,6 @@
"TITLE": "Promouvoir ce ticket en nouveau récit utilisateur", "TITLE": "Promouvoir ce ticket en nouveau récit utilisateur",
"MESSAGE": "Êtes-vous sure de vouloir créer un nouveau récit utilisateur à partir de ce ticket ?" "MESSAGE": "Êtes-vous sure de vouloir créer un nouveau récit utilisateur à partir de ce ticket ?"
}, },
"FILTERS": {
"TITLE": "Filtres",
"INPUT_SEARCH_PLACEHOLDER": "Objet ou réf.",
"TITLE_ACTION_SEARCH": "Rechercher",
"ACTION_SAVE_CUSTOM_FILTER": "sauvegarder en tant que filtre personnalisé",
"BREADCRUMB": "Filtres",
"TITLE_BREADCRUMB": "Filtres",
"CATEGORIES": {
"TYPE": "Type",
"STATUS": "Statut",
"SEVERITY": "Gravité",
"PRIORITIES": "Priorités",
"TAGS": "Mots-clés",
"ASSIGNED_TO": "Affecté à",
"CREATED_BY": "Créé par",
"CUSTOM_FILTERS": "Filtres personnalisés"
},
"CONFIRM_DELETE": {
"TITLE": "Supprime le filtre personnalisé",
"MESSAGE": "le filtre personnalisé '{{customFilterName}}'"
}
},
"TABLE": { "TABLE": {
"COLUMNS": { "COLUMNS": {
"TYPE": "Type", "TYPE": "Type",
@ -1316,6 +1436,7 @@
"SEARCH": { "SEARCH": {
"PAGE_TITLE": "Chercher - {{projectName}}", "PAGE_TITLE": "Chercher - {{projectName}}",
"PAGE_DESCRIPTION": "Chercher tout, récits utilisateurs, tickets, tâches ou pages de wiki, dans le projet {{projectName}} : {{projectDescription}}", "PAGE_DESCRIPTION": "Chercher tout, récits utilisateurs, tickets, tâches ou pages de wiki, dans le projet {{projectName}} : {{projectDescription}}",
"FILTER_EPICS": "Épopées",
"FILTER_USER_STORIES": "Récits utilisateur", "FILTER_USER_STORIES": "Récits utilisateur",
"FILTER_ISSUES": "Tickets", "FILTER_ISSUES": "Tickets",
"FILTER_TASKS": "Tâches", "FILTER_TASKS": "Tâches",
@ -1417,13 +1538,24 @@
"DELETE_LIGHTBOX_TITLE": "Supprimer la page Wiki", "DELETE_LIGHTBOX_TITLE": "Supprimer la page Wiki",
"DELETE_LINK_TITLE": "Supprimer un lien Wiki", "DELETE_LINK_TITLE": "Supprimer un lien Wiki",
"NAVIGATION": { "NAVIGATION": {
"SECTION_NAME": "Liens", "HOME": "Page principale",
"ACTION_ADD_LINK": "Ajouter un lien" "SECTION_NAME": "SIGNETS",
"ACTION_ADD_LINK": "Ajouter un signet",
"ALL_PAGES": "Toutes les pages wiki"
}, },
"SUMMARY": { "SUMMARY": {
"TIMES_EDITED": "modifications", "TIMES_EDITED": "modifications",
"LAST_EDIT": "dernière <br />modification", "LAST_EDIT": "dernière <br />modification",
"LAST_MODIFICATION": "dernière modification" "LAST_MODIFICATION": "dernière modification"
},
"SECTION_PAGES_LIST": "Toutes les pages",
"PAGES_LIST_COLUMNS": {
"TITLE": "Titre",
"EDITIONS": "Modifications",
"CREATED": "Créé le",
"MODIFIED": "Modifié",
"CREATOR": "Créateur",
"LAST_MODIFIER": "Dernier modificateur"
} }
}, },
"HINTS": { "HINTS": {
@ -1447,6 +1579,8 @@
"TASK_CREATED_WITH_US": "{{username}} a créé une nouvelle tâche {{obj_name}} dans le projet {{project_name}} pour le récit utilisateur {{us_name}}", "TASK_CREATED_WITH_US": "{{username}} a créé une nouvelle tâche {{obj_name}} dans le projet {{project_name}} pour le récit utilisateur {{us_name}}",
"WIKI_CREATED": "{{username}} a créé une nouvelle page wiki {{obj_name}} dans {{project_name}}", "WIKI_CREATED": "{{username}} a créé une nouvelle page wiki {{obj_name}} dans {{project_name}}",
"MILESTONE_CREATED": "{{username}} a créé un nouveau sprint {{obj_name}} dans {{project_name}}", "MILESTONE_CREATED": "{{username}} a créé un nouveau sprint {{obj_name}} dans {{project_name}}",
"EPIC_CREATED": "{{username}} has created a new epic {{obj_name}} in {{project_name}}",
"EPIC_RELATED_USERSTORY_CREATED": "{{username}} has related the userstory {{related_us_name}} to the epic {{epic_name}} in {{project_name}}",
"NEW_PROJECT": "{{username}} a créé le projet {{project_name}}", "NEW_PROJECT": "{{username}} a créé le projet {{project_name}}",
"MILESTONE_UPDATED": "{{username}} a mis à jour le sprint {{obj_name}}", "MILESTONE_UPDATED": "{{username}} a mis à jour le sprint {{obj_name}}",
"US_UPDATED": "{{username}} a mis à jour l'attribut «{{field_name}}» du récit utilisateur {{obj_name}}", "US_UPDATED": "{{username}} a mis à jour l'attribut «{{field_name}}» du récit utilisateur {{obj_name}}",
@ -1459,9 +1593,13 @@
"TASK_UPDATED_WITH_US": "{{username}} a mis à jour l'attribut «{{field_name}}» de la tâche {{obj_name}} qui appartient au récit utilisateur {{us_name}}", "TASK_UPDATED_WITH_US": "{{username}} a mis à jour l'attribut «{{field_name}}» de la tâche {{obj_name}} qui appartient au récit utilisateur {{us_name}}",
"TASK_UPDATED_WITH_US_NEW_VALUE": "{{username}} a mis l'attribut \"{{field_name}}\" à {{new_value}} pour la tâche {{obj_name}} appartenant au récit utilisateur {{us_name}}", "TASK_UPDATED_WITH_US_NEW_VALUE": "{{username}} a mis l'attribut \"{{field_name}}\" à {{new_value}} pour la tâche {{obj_name}} appartenant au récit utilisateur {{us_name}}",
"WIKI_UPDATED": "{{username}} a mis à jour la page wiki {{obj_name}}", "WIKI_UPDATED": "{{username}} a mis à jour la page wiki {{obj_name}}",
"EPIC_UPDATED": "{{username}} has updated the attribute \"{{field_name}}\" of the epic {{obj_name}}",
"EPIC_UPDATED_WITH_NEW_VALUE": "{{username}} has updated the attribute \"{{field_name}}\" of the epic {{obj_name}} to {{new_value}}",
"EPIC_UPDATED_WITH_NEW_COLOR": "{{username}} has updated the \"{{field_name}}\" of the epic {{obj_name}} to <span class=\"new-color\" style=\"background: {{new_value}}\"></span>",
"NEW_COMMENT_US": "{{username}} a commenté le récit utilisateur {{obj_name}}", "NEW_COMMENT_US": "{{username}} a commenté le récit utilisateur {{obj_name}}",
"NEW_COMMENT_ISSUE": "{{username}} a commenté le ticket {{obj_name}}", "NEW_COMMENT_ISSUE": "{{username}} a commenté le ticket {{obj_name}}",
"NEW_COMMENT_TASK": "{{username}} a commenté la tâche {{obj_name}}", "NEW_COMMENT_TASK": "{{username}} a commenté la tâche {{obj_name}}",
"NEW_COMMENT_EPIC": "{{username}} has commented in the epic {{obj_name}}",
"NEW_MEMBER": "{{project_name}} a un nouveau membre", "NEW_MEMBER": "{{project_name}} a un nouveau membre",
"US_ADDED_MILESTONE": "{{username}} a ajouté le récit utilisateur {{obj_name}} à {{sprint_name}}", "US_ADDED_MILESTONE": "{{username}} a ajouté le récit utilisateur {{obj_name}} à {{sprint_name}}",
"US_MOVED": "{{username}} a déplacé le RU {{obj_name}}", "US_MOVED": "{{username}} a déplacé le RU {{obj_name}}",

View File

@ -35,6 +35,8 @@
"ONE_ITEM_LINE": "Un elemento per riga...", "ONE_ITEM_LINE": "Un elemento per riga...",
"NEW_BULK": "Nuovo inserimento nel carico", "NEW_BULK": "Nuovo inserimento nel carico",
"RELATED_TASKS": "Compiti correlati", "RELATED_TASKS": "Compiti correlati",
"PREVIOUS": "Previous",
"NEXT": "Successivo",
"LOGOUT": "Esci", "LOGOUT": "Esci",
"EXTERNAL_USER": "un utente esterno", "EXTERNAL_USER": "un utente esterno",
"GENERIC_ERROR": "C'é uno dei nostri Oompa Loompa che dice {{error}}.", "GENERIC_ERROR": "C'é uno dei nostri Oompa Loompa che dice {{error}}.",
@ -45,6 +47,11 @@
"CAPSLOCK_WARNING": "Be careful! You are using capital letters in an input field that is case sensitive.", "CAPSLOCK_WARNING": "Be careful! You are using capital letters in an input field that is case sensitive.",
"CONFIRM_CLOSE_EDIT_MODE_TITLE": "Are you sure you want to close the edit mode?", "CONFIRM_CLOSE_EDIT_MODE_TITLE": "Are you sure you want to close the edit mode?",
"CONFIRM_CLOSE_EDIT_MODE_MESSAGE": "Remember that if you close the edit mode without saving all the changes will be lost", "CONFIRM_CLOSE_EDIT_MODE_MESSAGE": "Remember that if you close the edit mode without saving all the changes will be lost",
"RELATED_USERSTORIES": "Related user stories",
"CARD": {
"ASSIGN_TO": "Assign To",
"EDIT": "Edit card"
},
"FORM_ERRORS": { "FORM_ERRORS": {
"DEFAULT_MESSAGE": "Questo valore non è valido.", "DEFAULT_MESSAGE": "Questo valore non è valido.",
"TYPE_EMAIL": "Questo valore dovrebbe corrispondere ad una mail valida", "TYPE_EMAIL": "Questo valore dovrebbe corrispondere ad una mail valida",
@ -115,8 +122,9 @@
"USER_STORY": "Storia utente", "USER_STORY": "Storia utente",
"TASK": "Compito", "TASK": "Compito",
"ISSUE": "Problema", "ISSUE": "Problema",
"EPIC": "Epic",
"TAGS": { "TAGS": {
"PLACEHOLDER": "Eccomi! taggami", "PLACEHOLDER": "Enter tag",
"DELETE": "Elimina tag", "DELETE": "Elimina tag",
"ADD": "Aggiungi un tag" "ADD": "Aggiungi un tag"
}, },
@ -193,12 +201,29 @@
"CONFIRM_DELETE": "Ricorda che tutti i valori in questo campo custom andranno persi.\nSei sicuro di voler continuare?" "CONFIRM_DELETE": "Ricorda che tutti i valori in questo campo custom andranno persi.\nSei sicuro di voler continuare?"
}, },
"FILTERS": { "FILTERS": {
"TITLE": "filtri", "TITLE": "Filtri",
"INPUT_PLACEHOLDER": "Soggetto o referenza", "INPUT_PLACEHOLDER": "Soggetto o referenza",
"TITLE_ACTION_FILTER_BUTTON": "cerca", "TITLE_ACTION_FILTER_BUTTON": "cerca",
"BREADCRUMB_TITLE": "Indietro alle categorie", "INPUT_SEARCH_PLACEHOLDER": "Soggetto o referenza",
"BREADCRUMB_FILTERS": "Filtri", "TITLE_ACTION_SEARCH": "Cerca",
"BREADCRUMB_STATUS": "stato" "ACTION_SAVE_CUSTOM_FILTER": "salva come filtro personalizzato",
"PLACEHOLDER_FILTER_NAME": "Scrivi il nome del filtro e premi invio",
"APPLIED_FILTERS_NUM": "filters applied",
"CATEGORIES": {
"TYPE": "Tipo",
"STATUS": "Stato",
"SEVERITY": "Gravità",
"PRIORITIES": "Priorità",
"TAGS": "Tag",
"ASSIGNED_TO": "Assegnato a",
"CREATED_BY": "Creato da",
"CUSTOM_FILTERS": "Filtri personalizzati",
"EPIC": "Epic"
},
"CONFIRM_DELETE": {
"TITLE": "Elimina il filtro personalizzato",
"MESSAGE": "Il filtro personalizzato '{{customFilterName}}'"
}
}, },
"WYSIWYG": { "WYSIWYG": {
"H1_BUTTON": "Intestazione di primo livello", "H1_BUTTON": "Intestazione di primo livello",
@ -228,9 +253,18 @@
"PREVIEW_BUTTON": "Anteprima", "PREVIEW_BUTTON": "Anteprima",
"EDIT_BUTTON": "Modifica", "EDIT_BUTTON": "Modifica",
"ATTACH_FILE_HELP": "Attach files by dragging & dropping on the textarea above.", "ATTACH_FILE_HELP": "Attach files by dragging & dropping on the textarea above.",
"ATTACH_FILE_HELP_SAVE_FIRST": "Save first before if you want to attach files by dragging & dropping on the textarea above.",
"MARKDOWN_HELP": "Aiuto per la sintassi Markdown" "MARKDOWN_HELP": "Aiuto per la sintassi Markdown"
}, },
"PERMISIONS_CATEGORIES": { "PERMISIONS_CATEGORIES": {
"EPICS": {
"NAME": "Epics",
"VIEW_EPICS": "View epics",
"ADD_EPICS": "Add epics",
"MODIFY_EPICS": "Modify epics",
"COMMENT_EPICS": "Comment epics",
"DELETE_EPICS": "Delete epics"
},
"SPRINTS": { "SPRINTS": {
"NAME": "Sprints", "NAME": "Sprints",
"VIEW_SPRINTS": "Vedi gli sprint", "VIEW_SPRINTS": "Vedi gli sprint",
@ -243,6 +277,7 @@
"VIEW_USER_STORIES": "Vai alle storie utente", "VIEW_USER_STORIES": "Vai alle storie utente",
"ADD_USER_STORIES": "Aggiungi le storie utente", "ADD_USER_STORIES": "Aggiungi le storie utente",
"MODIFY_USER_STORIES": "Modifica le storie utente", "MODIFY_USER_STORIES": "Modifica le storie utente",
"COMMENT_USER_STORIES": "Comment user stories",
"DELETE_USER_STORIES": "Elimina le storie utente" "DELETE_USER_STORIES": "Elimina le storie utente"
}, },
"TASKS": { "TASKS": {
@ -250,6 +285,7 @@
"VIEW_TASKS": "Guarda i compiti", "VIEW_TASKS": "Guarda i compiti",
"ADD_TASKS": "Aggiungi i compiti", "ADD_TASKS": "Aggiungi i compiti",
"MODIFY_TASKS": "Modifica i compiti", "MODIFY_TASKS": "Modifica i compiti",
"COMMENT_TASKS": "Comment tasks",
"DELETE_TASKS": "Elimina i compiti" "DELETE_TASKS": "Elimina i compiti"
}, },
"ISSUES": { "ISSUES": {
@ -257,6 +293,7 @@
"VIEW_ISSUES": "Guarda i problemi", "VIEW_ISSUES": "Guarda i problemi",
"ADD_ISSUES": "Aggiungi un problema", "ADD_ISSUES": "Aggiungi un problema",
"MODIFY_ISSUES": "Modifica i problemi", "MODIFY_ISSUES": "Modifica i problemi",
"COMMENT_ISSUES": "Comment issues",
"DELETE_ISSUES": "Elimina i problemi" "DELETE_ISSUES": "Elimina i problemi"
}, },
"WIKI": { "WIKI": {
@ -366,6 +403,41 @@
"WATCHING_SECTION": "Osservando", "WATCHING_SECTION": "Osservando",
"DASHBOARD": "Dashboard Progetti" "DASHBOARD": "Dashboard Progetti"
}, },
"EPICS": {
"TITLE": "EPICS",
"SECTION_NAME": "Epics",
"EPIC": "EPIC",
"PAGE_TITLE": "Epics - {{projectName}}",
"PAGE_DESCRIPTION": "The epics list of the project {{projectName}}: {{projectDescription}}",
"DASHBOARD": {
"ADD": "+ ADD EPIC",
"UNASSIGNED": "Non assegnato"
},
"EMPTY": {
"TITLE": "It looks like there aren't any epics yet",
"EXPLANATION": "Epics are items at a higher level that encompass user stories.<br />Epics are at the top of the hierarchy and can be used to group user stories together.",
"HELP": "Learn more about epics"
},
"TABLE": {
"VOTES": "Voti",
"NAME": "Nome",
"PROJECT": "Progetto",
"SPRINT": "Sprint",
"ASSIGNED_TO": "Assigned",
"STATUS": "Stato",
"PROGRESS": "Progress",
"VIEW_OPTIONS": "View options"
},
"CREATE": {
"TITLE": "New Epic",
"PLACEHOLDER_DESCRIPTION": "Please add descriptive text to help others better understand this epic",
"TEAM_REQUIREMENT": "Team requirement",
"CLIENT_REQUIREMENT": "Client requirement",
"BLOCKED": "Bloccato",
"BLOCKED_NOTE_PLACEHOLDER": "Why is this epic blocked?",
"CREATE_EPIC": "Create epic"
}
},
"PROJECTS": { "PROJECTS": {
"PAGE_TITLE": "I miei progetti - Taiga", "PAGE_TITLE": "I miei progetti - Taiga",
"PAGE_DESCRIPTION": "Una lista di tutti i tuoi progetti, la puoi riordinare o crearne una nuova.", "PAGE_DESCRIPTION": "Una lista di tutti i tuoi progetti, la puoi riordinare o crearne una nuova.",
@ -402,7 +474,8 @@
"ADMIN": { "ADMIN": {
"COMMON": { "COMMON": {
"TITLE_ACTION_EDIT_VALUE": "Modifica valore", "TITLE_ACTION_EDIT_VALUE": "Modifica valore",
"TITLE_ACTION_DELETE_VALUE": "Elimina valore" "TITLE_ACTION_DELETE_VALUE": "Elimina valore",
"TITLE_ACTION_DELETE_TAG": "Elimina tag"
}, },
"HELP": "Hai bisogno di aiuto? Controlla la nostra pagina di supporto!", "HELP": "Hai bisogno di aiuto? Controlla la nostra pagina di supporto!",
"PROJECT_DEFAULT_VALUES": { "PROJECT_DEFAULT_VALUES": {
@ -435,6 +508,8 @@
"TITLE": "Moduli", "TITLE": "Moduli",
"ENABLE": "Abilita", "ENABLE": "Abilita",
"DISABLE": "Disabilita", "DISABLE": "Disabilita",
"EPICS": "Epics",
"EPICS_DESCRIPTION": "Visualize and manage the most strategic part of your project",
"BACKLOG": "Backlog", "BACKLOG": "Backlog",
"BACKLOG_DESCRIPTION": "Amministra le storie degli utenti per mantenere una visione organizzata dei lavori in arrivo e di quelli ad alta priorità ", "BACKLOG_DESCRIPTION": "Amministra le storie degli utenti per mantenere una visione organizzata dei lavori in arrivo e di quelli ad alta priorità ",
"NUMBER_SPRINTS": "Expected number of sprints", "NUMBER_SPRINTS": "Expected number of sprints",
@ -497,6 +572,7 @@
"REGENERATE_SUBTITLE": "Stai per modificare l'url di accesso al CSV. il precedente url verrá disabilitato. Sei sicuro?" "REGENERATE_SUBTITLE": "Stai per modificare l'url di accesso al CSV. il precedente url verrá disabilitato. Sei sicuro?"
}, },
"CSV": { "CSV": {
"SECTION_TITLE_EPIC": "epics reports",
"SECTION_TITLE_US": "Report delle storie utente", "SECTION_TITLE_US": "Report delle storie utente",
"SECTION_TITLE_TASK": "Analisi dei compiti", "SECTION_TITLE_TASK": "Analisi dei compiti",
"SECTION_TITLE_ISSUE": "Report criticitá", "SECTION_TITLE_ISSUE": "Report criticitá",
@ -509,6 +585,8 @@
"CUSTOM_FIELDS": { "CUSTOM_FIELDS": {
"TITLE": "Campi Personalizzati", "TITLE": "Campi Personalizzati",
"SUBTITLE": "Specifica i campi personalizzati per le tue Storie Utente, compiti e problemi", "SUBTITLE": "Specifica i campi personalizzati per le tue Storie Utente, compiti e problemi",
"EPIC_DESCRIPTION": "Epics custom fields",
"EPIC_ADD": "Add a custom field in epics",
"US_DESCRIPTION": "Campi personalizzati delle storie utente", "US_DESCRIPTION": "Campi personalizzati delle storie utente",
"US_ADD": "Aggiungi un campo personalizzato nelle storie utente", "US_ADD": "Aggiungi un campo personalizzato nelle storie utente",
"TASK_DESCRIPTION": "Campi personalizzati dei Compiti", "TASK_DESCRIPTION": "Campi personalizzati dei Compiti",
@ -546,7 +624,8 @@
"PROJECT_VALUES_STATUS": { "PROJECT_VALUES_STATUS": {
"TITLE": "Stato", "TITLE": "Stato",
"SUBTITLE": "Specifica lo stato delle storie utente, i compiti e i problemi saranno affrontati", "SUBTITLE": "Specifica lo stato delle storie utente, i compiti e i problemi saranno affrontati",
"US_TITLE": "Stato delle storie utente", "EPIC_TITLE": "Epic Statuses",
"US_TITLE": "User Story Statuses",
"TASK_TITLE": "Stato dei compiti", "TASK_TITLE": "Stato dei compiti",
"ISSUE_TITLE": "Stato dei problemi" "ISSUE_TITLE": "Stato dei problemi"
}, },
@ -556,6 +635,17 @@
"ISSUE_TITLE": "Tipi di criticitá", "ISSUE_TITLE": "Tipi di criticitá",
"ACTION_ADD": "Aggiungi {{objName}}" "ACTION_ADD": "Aggiungi {{objName}}"
}, },
"PROJECT_VALUES_TAGS": {
"TITLE": "Tag",
"SUBTITLE": "View and edit the color of your tags",
"EMPTY": "Currently there are no tags",
"EMPTY_SEARCH": "It looks like nothing was found with your search criteria",
"ACTION_ADD": "Aggiungi un tag",
"NEW_TAG": "New tag",
"MIXING_HELP_TEXT": "Select the tags that you want to merge",
"MIXING_MERGE": "Merge Tags",
"SELECTED": "Selected"
},
"ROLES": { "ROLES": {
"PAGE_TITLE": "Ruoli - {{projectName}}", "PAGE_TITLE": "Ruoli - {{projectName}}",
"WARNING_NO_ROLE": "Attento, nessun ruolo, all'interno del tuo progetto, potrà stimare i punti valore per le storie utente", "WARNING_NO_ROLE": "Attento, nessun ruolo, all'interno del tuo progetto, potrà stimare i punti valore per le storie utente",
@ -588,6 +678,10 @@
"SECTION_NAME": "Github", "SECTION_NAME": "Github",
"PAGE_TITLE": "Github - {{projectName}}" "PAGE_TITLE": "Github - {{projectName}}"
}, },
"GOGS": {
"SECTION_NAME": "Gogs",
"PAGE_TITLE": "Gogs - {{projectName}}"
},
"WEBHOOKS": { "WEBHOOKS": {
"PAGE_TITLE": "Webhooks - {{projectName}}", "PAGE_TITLE": "Webhooks - {{projectName}}",
"SECTION_NAME": "Webhooks", "SECTION_NAME": "Webhooks",
@ -643,13 +737,14 @@
"DEFAULT_DELETE_MESSAGE": "L'invito a {{email}}" "DEFAULT_DELETE_MESSAGE": "L'invito a {{email}}"
}, },
"DEFAULT_VALUES": { "DEFAULT_VALUES": {
"LABEL_EPIC_STATUS": "Default value for epic status selector",
"LABEL_US_STATUS": "Default value for user story status selector",
"LABEL_POINTS": "Valore standard per punti di selezione", "LABEL_POINTS": "Valore standard per punti di selezione",
"LABEL_US": "Valore predefinito per la selezione di stati delle storie utente",
"LABEL_TASK_STATUS": "Valore predefinito per la selezione degli stati del compito", "LABEL_TASK_STATUS": "Valore predefinito per la selezione degli stati del compito",
"LABEL_PRIORITY": "Valore predefinito per la selezione prioritaria",
"LABEL_SEVERITY": "Valore predefinito per la selezione di rigore",
"LABEL_ISSUE_TYPE": "Valore predefinito per il tipo di selezione del problema", "LABEL_ISSUE_TYPE": "Valore predefinito per il tipo di selezione del problema",
"LABEL_ISSUE_STATUS": "Valore predefinito per la selezione di stato del problema" "LABEL_ISSUE_STATUS": "Valore predefinito per la selezione di stato del problema",
"LABEL_PRIORITY": "Valore predefinito per la selezione prioritaria",
"LABEL_SEVERITY": "Valore predefinito per la selezione di rigore"
}, },
"STATUS": { "STATUS": {
"PLACEHOLDER_WRITE_STATUS_NAME": "Scrivi un nome per il nuovo status" "PLACEHOLDER_WRITE_STATUS_NAME": "Scrivi un nome per il nuovo status"
@ -681,7 +776,8 @@
"PRIORITIES": "priorità", "PRIORITIES": "priorità",
"SEVERITIES": "Severitá", "SEVERITIES": "Severitá",
"TYPES": "Tipi", "TYPES": "Tipi",
"CUSTOM_FIELDS": "Campi personalizzati" "CUSTOM_FIELDS": "Campi personalizzati",
"TAGS": "Tag"
}, },
"SUBMENU_PROJECT_PROFILE": { "SUBMENU_PROJECT_PROFILE": {
"TITLE": "Profilo progetto" "TITLE": "Profilo progetto"
@ -751,6 +847,8 @@
"FILTER_TYPE_ALL_TITLE": "Mostra tutto", "FILTER_TYPE_ALL_TITLE": "Mostra tutto",
"FILTER_TYPE_PROJECTS": "Progetti", "FILTER_TYPE_PROJECTS": "Progetti",
"FILTER_TYPE_PROJECT_TITLES": "Mostra solo i progetti", "FILTER_TYPE_PROJECT_TITLES": "Mostra solo i progetti",
"FILTER_TYPE_EPICS": "Epics",
"FILTER_TYPE_EPIC_TITLES": "Show only epics",
"FILTER_TYPE_USER_STORIES": "Resoconti", "FILTER_TYPE_USER_STORIES": "Resoconti",
"FILTER_TYPE_USER_STORIES_TITLES": "Mostra solo resoconti utente", "FILTER_TYPE_USER_STORIES_TITLES": "Mostra solo resoconti utente",
"FILTER_TYPE_TASKS": "Compiti", "FILTER_TYPE_TASKS": "Compiti",
@ -950,8 +1048,8 @@
"CREATE_MEMBER": { "CREATE_MEMBER": {
"PLACEHOLDER_INVITATION_TEXT": "(facoltativo) aggiungi un testo personalizzato all'invito. Di qualcosa di simpatico ai tuoi nuovi membri ;-)", "PLACEHOLDER_INVITATION_TEXT": "(facoltativo) aggiungi un testo personalizzato all'invito. Di qualcosa di simpatico ai tuoi nuovi membri ;-)",
"PLACEHOLDER_TYPE_EMAIL": "Scrivi una mail", "PLACEHOLDER_TYPE_EMAIL": "Scrivi una mail",
"LIMIT_USERS_WARNING_MESSAGE_FOR_OWNER": "Unfortunately, this project can't have more than <strong>{{maxMembers}}</strong> members.<br> If you would like to increase the current limit, please contact the administrator.", "LIMIT_USERS_WARNING_MESSAGE_FOR_OWNER": "You are about to reach the maximum number of members allowed for this project, <strong>{{maxMembers}}</strong> members. If you would like to increase the current limit, please contact the administrator.",
"LIMIT_USERS_WARNING_MESSAGE": "Unfortunately, this project can't have more than <strong>{{maxMembers}}</strong> members." "LIMIT_USERS_WARNING_MESSAGE": "You are about to reach the maximum number of members allowed for this project, <strong>{{maxMembers}}</strong> members."
}, },
"LEAVE_PROJECT_WARNING": { "LEAVE_PROJECT_WARNING": {
"TITLE": "Unfortunately, this project can't be left without an owner", "TITLE": "Unfortunately, this project can't be left without an owner",
@ -970,10 +1068,30 @@
"BUTTON": "Ask this project member to become the new project owner" "BUTTON": "Ask this project member to become the new project owner"
} }
}, },
"EPIC": {
"PAGE_TITLE": "{{epicSubject}} - Epic {{epicRef}} - {{projectName}}",
"PAGE_DESCRIPTION": "Status: {{epicStatus }}. Description: {{epicDescription}}",
"SECTION_NAME": "Epic",
"TITLE_LIGHTBOX_UNLINK_RELATED_USERSTORY": "Unlink related userstory",
"MSG_LIGHTBOX_UNLINK_RELATED_USERSTORY": "It will delete the link to the related userstory '{{subject}}'",
"ERROR_UNLINK_RELATED_USERSTORY": "We have not been able to unlink: {{errorMessage}}",
"CREATE_RELATED_USERSTORIES": "Create a relationship with",
"NEW_USERSTORY": "Nuova storia utente",
"EXISTING_USERSTORY": "Existing user story",
"CHOOSE_PROJECT_FOR_CREATION": "What's the project?",
"SUBJECT": "Oggetto",
"SUBJECT_BULK_MODE": "Subject (bulk insert)",
"CHOOSE_PROJECT_FROM": "What's the project?",
"CHOOSE_USERSTORY": "What's the user story?",
"NO_USERSTORIES": "This project has no User Stories yet. Please select another project.",
"FILTER_USERSTORIES": "Filter user stories",
"LIGHTBOX_TITLE_BLOKING_EPIC": "Blocking epic",
"ACTION_DELETE": "Delete epic"
},
"US": { "US": {
"PAGE_TITLE": "{{userStorySubject}} - User Story {{userStoryRef}} - {{projectName}}", "PAGE_TITLE": "{{userStorySubject}} - User Story {{userStoryRef}} - {{projectName}}",
"PAGE_DESCRIPTION": "Status: {{userStoryStatus }}. Completata per il {{userStoryProgressPercentage}}% ({{userStoryClosedTasks}} di {{userStoryTotalTasks}} tasks closed). Punti: {{userStoryPoints}}. Descrizione: {{userStoryDescription}}", "PAGE_DESCRIPTION": "Status: {{userStoryStatus }}. Completata per il {{userStoryProgressPercentage}}% ({{userStoryClosedTasks}} di {{userStoryTotalTasks}} tasks closed). Punti: {{userStoryPoints}}. Descrizione: {{userStoryDescription}}",
"SECTION_NAME": "Dettagli della storia utente", "SECTION_NAME": "Storia utente",
"LINK_TASKBOARD": "Pannello dei compiti", "LINK_TASKBOARD": "Pannello dei compiti",
"TITLE_LINK_TASKBOARD": "Vai al pannello dei compiti", "TITLE_LINK_TASKBOARD": "Vai al pannello dei compiti",
"TOTAL_POINTS": "totale punti", "TOTAL_POINTS": "totale punti",
@ -984,14 +1102,23 @@
"EXTERNAL_REFERENCE": "Questo US é stato creato da", "EXTERNAL_REFERENCE": "Questo US é stato creato da",
"GO_TO_EXTERNAL_REFERENCE": "Ritorna all'inizio", "GO_TO_EXTERNAL_REFERENCE": "Ritorna all'inizio",
"BLOCKED": "Questa storia utente è bloccata", "BLOCKED": "Questa storia utente è bloccata",
"PREVIOUS": "Storia utente precedente ",
"NEXT": "Prossima storia utente",
"TITLE_DELETE_ACTION": "Elimina la storia utente", "TITLE_DELETE_ACTION": "Elimina la storia utente",
"LIGHTBOX_TITLE_BLOKING_US": "Blocco la storia utente", "LIGHTBOX_TITLE_BLOKING_US": "Blocco la storia utente",
"TASK_COMPLETED": "{{totalClosedTasks}}/{{totalTasks}} compiti completati", "TASK_COMPLETED": "{{totalClosedTasks}}/{{totalTasks}} compiti completati",
"ASSIGN": "Assegna la storia utente", "ASSIGN": "Assegna la storia utente",
"NOT_ESTIMATED": "Non stimato", "NOT_ESTIMATED": "Non stimato",
"TOTAL_US_POINTS": "Totale punti della storia utente", "TOTAL_US_POINTS": "Totale punti della storia utente",
"TRIBE": {
"PUBLISH": "Publish as Gig in Taiga Tribe",
"PUBLISH_INFO": "More info",
"PUBLISH_TITLE": "More info on publishing in Taiga Tribe",
"PUBLISHED_AS_GIG": "Story published as Gig in Taiga Tribe",
"EDIT_LINK": "Edit link",
"CLOSE": "Close",
"SYNCHRONIZE_LINK": "synchronize with Taiga Tribe",
"PUBLISH_MORE_INFO_TITLE": "Do you need somebody for this task?",
"PUBLISH_MORE_INFO_TEXT": "<p>If you need help with a particular piece of work you can easily create gigs on<a href='taigatribe.com' title='Taiga Tribe'> Taiga Tribe </a> and receive help from all over the world. You will be able to control and manage the gig enjoying a great community eager to contribute.</p><p><a href='taigatribe.com' title='Taiga Tribe'> TaigaTribe </a> was born as a Taiga sibling. Both platforms can live separately but we believe that there is much power in using them combined so we are making sure the integration works like a charm.</p>"
},
"FIELDS": { "FIELDS": {
"TEAM_REQUIREMENT": "Requisito del team", "TEAM_REQUIREMENT": "Requisito del team",
"CLIENT_REQUIREMENT": "Requisito del client", "CLIENT_REQUIREMENT": "Requisito del client",
@ -999,28 +1126,47 @@
} }
}, },
"COMMENTS": { "COMMENTS": {
"DELETED_INFO": "Commento cancellato da {{user}} il {{date}}", "DELETED_INFO": "Comment deleted by {{user}}",
"TITLE": "Commenti", "TITLE": "Commenti",
"COMMENTS_COUNT": "{{comments}} Comments",
"ORDER": "Order",
"OLDER_FIRST": "Older first",
"RECENT_FIRST": "Recent first",
"COMMENT": "Commento", "COMMENT": "Commento",
"EDIT_COMMENT": "Edit comment",
"EDITED_COMMENT": "Edited:",
"SHOW_HISTORY": "View historic",
"TYPE_NEW_COMMENT": "Scrivi un nuovo commento qui", "TYPE_NEW_COMMENT": "Scrivi un nuovo commento qui",
"SHOW_DELETED": "Visualizza commento cancellato", "SHOW_DELETED": "Visualizza commento cancellato",
"HIDE_DELETED": "Nascondi commento cancellato", "HIDE_DELETED": "Nascondi commento cancellato",
"DELETE": "Cancella commento", "DELETE": "Cancella commento",
"RESTORE": "Ripristina commento" "RESTORE": "Ripristina commento",
"HISTORY": {
"TITLE": "Attività"
}
}, },
"ACTIVITY": { "ACTIVITY": {
"SHOW_ACTIVITY": "Mostra attività", "SHOW_ACTIVITY": "Mostra attività",
"DATETIME": "DD MMM YYYY HH:mm", "DATETIME": "DD MMM YYYY HH:mm",
"SHOW_MORE": "Mostra gli inserimenti precedenti ({{showMore}} more)", "SHOW_MORE": "Mostra gli inserimenti precedenti ({{showMore}} more)",
"TITLE": "Attività", "TITLE": "Attività",
"ACTIVITIES_COUNT": "{{activities}} Activities",
"REMOVED": "rimosso", "REMOVED": "rimosso",
"ADDED": "aggiunto", "ADDED": "aggiunto",
"US_POINTS": "punti storia utente ({{name}})", "TAGS_ADDED": "tags added:",
"NEW_ATTACHMENT": "nuovo allegato", "TAGS_REMOVED": "tags removed:",
"DELETED_ATTACHMENT": "allegato eliminato", "US_POINTS": "{{role}} points",
"UPDATED_ATTACHMENT": "Aggiornato l'allegato {{filename}}", "NEW_ATTACHMENT": "new attachment:",
"DELETED_CUSTOM_ATTRIBUTE": "elimina un attributo personalizzato", "DELETED_ATTACHMENT": "deleted attachment:",
"UPDATED_ATTACHMENT": "updated attachment ({{filename}}):",
"CREATED_CUSTOM_ATTRIBUTE": "created custom attribute",
"UPDATED_CUSTOM_ATTRIBUTE": "updated custom attribute",
"SIZE_CHANGE": "Fatto {size, plural, one{un cambiamento} other{# cambiamenti}}", "SIZE_CHANGE": "Fatto {size, plural, one{un cambiamento} other{# cambiamenti}}",
"BECAME_DEPRECATED": "became deprecated",
"BECAME_UNDEPRECATED": "became undeprecated",
"TEAM_REQUIREMENT": "Requisito del team",
"CLIENT_REQUIREMENT": "Requisito del client",
"BLOCKED": "Bloccato",
"VALUES": { "VALUES": {
"YES": "si", "YES": "si",
"NO": "no", "NO": "no",
@ -1052,12 +1198,14 @@
"TAGS": "tag", "TAGS": "tag",
"ATTACHMENTS": "allegati", "ATTACHMENTS": "allegati",
"IS_DEPRECATED": "è deprecato", "IS_DEPRECATED": "è deprecato",
"IS_NOT_DEPRECATED": "is not deprecated",
"ORDER": "ordine", "ORDER": "ordine",
"BACKLOG_ORDER": "Ordine di backlog", "BACKLOG_ORDER": "Ordine di backlog",
"SPRINT_ORDER": "Ordine dello sprint", "SPRINT_ORDER": "Ordine dello sprint",
"KANBAN_ORDER": "ordina kanban", "KANBAN_ORDER": "ordina kanban",
"TASKBOARD_ORDER": "Ordine del pannello dei compiti", "TASKBOARD_ORDER": "Ordine del pannello dei compiti",
"US_ORDER": "Ordine delle storie utente" "US_ORDER": "Ordine delle storie utente",
"COLOR": "colore"
} }
}, },
"BACKLOG": { "BACKLOG": {
@ -1109,7 +1257,8 @@
"CLOSED_TASKS": "<br /> compiti chiusi", "CLOSED_TASKS": "<br /> compiti chiusi",
"IOCAINE_DOSES": "<br /> pasticche di aspirina", "IOCAINE_DOSES": "<br /> pasticche di aspirina",
"SHOW_STATISTICS_TITLE": "Mostra statistiche", "SHOW_STATISTICS_TITLE": "Mostra statistiche",
"TOGGLE_BAKLOG_GRAPH": "Mostra/nascondi i grafici burndown" "TOGGLE_BAKLOG_GRAPH": "Mostra/nascondi i grafici burndown",
"POINTS_PER_ROLE": "Points per role"
}, },
"SUMMARY": { "SUMMARY": {
"PROJECT_POINTS": "<br /> punti di progetto", "PROJECT_POINTS": "<br /> punti di progetto",
@ -1122,9 +1271,7 @@
"TITLE": "Filtri", "TITLE": "Filtri",
"REMOVE": "Rimuovi filtri", "REMOVE": "Rimuovi filtri",
"HIDE": "Nascondi Filtri", "HIDE": "Nascondi Filtri",
"SHOW": "Mostra Filtri", "SHOW": "Mostra Filtri"
"FILTER_CATEGORY_STATUS": "Stato",
"FILTER_CATEGORY_TAGS": "Tag"
}, },
"SPRINTS": { "SPRINTS": {
"TITLE": "SPRINTS", "TITLE": "SPRINTS",
@ -1179,7 +1326,7 @@
"TASK": { "TASK": {
"PAGE_TITLE": "{{taskSubject}} - Compiti {{taskRef}} - {{projectName}}", "PAGE_TITLE": "{{taskSubject}} - Compiti {{taskRef}} - {{projectName}}",
"PAGE_DESCRIPTION": "Stato: {{taskStatus }}. Descrizione: {{taskDescription}}", "PAGE_DESCRIPTION": "Stato: {{taskStatus }}. Descrizione: {{taskDescription}}",
"SECTION_NAME": "Dettagli del compito", "SECTION_NAME": "Compito",
"LINK_TASKBOARD": "Pannello dei compiti", "LINK_TASKBOARD": "Pannello dei compiti",
"TITLE_LINK_TASKBOARD": "Vai al pannello dei compiti", "TITLE_LINK_TASKBOARD": "Vai al pannello dei compiti",
"PLACEHOLDER_SUBJECT": "Inserisci il soggetto del nuovo compito", "PLACEHOLDER_SUBJECT": "Inserisci il soggetto del nuovo compito",
@ -1189,8 +1336,6 @@
"ORIGIN_US": "Questo compito è stato creato da", "ORIGIN_US": "Questo compito è stato creato da",
"TITLE_LINK_GO_ORIGIN": "Vai alla storia utente", "TITLE_LINK_GO_ORIGIN": "Vai alla storia utente",
"BLOCKED": "Questo compito è bloccato", "BLOCKED": "Questo compito è bloccato",
"PREVIOUS": "Compito precedente",
"NEXT": "Prossimo compito",
"TITLE_DELETE_ACTION": "Rimuovi compito", "TITLE_DELETE_ACTION": "Rimuovi compito",
"LIGHTBOX_TITLE_BLOKING_TASK": "Sto bloccando il compito", "LIGHTBOX_TITLE_BLOKING_TASK": "Sto bloccando il compito",
"FIELDS": { "FIELDS": {
@ -1228,16 +1373,13 @@
"PAGE_TITLE": "Criticitá - {{projectName}}", "PAGE_TITLE": "Criticitá - {{projectName}}",
"PAGE_DESCRIPTION": "Il pannello con la lista dei problemi del progetto {{projectName}}: {{projectDescription}}", "PAGE_DESCRIPTION": "Il pannello con la lista dei problemi del progetto {{projectName}}: {{projectDescription}}",
"LIST_SECTION_NAME": "problemi", "LIST_SECTION_NAME": "problemi",
"SECTION_NAME": "Dettagli della criticitá", "SECTION_NAME": "Problema",
"ACTION_NEW_ISSUE": "+ NUOVA CRITICITÁ", "ACTION_NEW_ISSUE": "+ NUOVA CRITICITÁ",
"ACTION_PROMOTE_TO_US": "Promuovi la storia utente", "ACTION_PROMOTE_TO_US": "Promuovi la storia utente",
"PLACEHOLDER_FILTER_NAME": "Scrivi il nome del filtro e premi invio",
"PROMOTED": "Il problema è stato promosso a storia utente", "PROMOTED": "Il problema è stato promosso a storia utente",
"EXTERNAL_REFERENCE": "Questo problema è stato creato da ", "EXTERNAL_REFERENCE": "Questo problema è stato creato da ",
"GO_TO_EXTERNAL_REFERENCE": "Ritorna all'inizio", "GO_TO_EXTERNAL_REFERENCE": "Ritorna all'inizio",
"BLOCKED": "Questo problema è bloccato", "BLOCKED": "Questo problema è bloccato",
"TITLE_PREVIOUS_ISSUE": "problema precedente",
"TITLE_NEXT_ISSUE": "Problema successivo",
"ACTION_DELETE": "Elimina problema", "ACTION_DELETE": "Elimina problema",
"LIGHTBOX_TITLE_BLOKING_ISSUE": "Issue bloccante", "LIGHTBOX_TITLE_BLOKING_ISSUE": "Issue bloccante",
"FIELDS": { "FIELDS": {
@ -1249,28 +1391,6 @@
"TITLE": "Promuovi questo problema come nuova storia utente", "TITLE": "Promuovi questo problema come nuova storia utente",
"MESSAGE": "Sei sicuro di voler creare una nuova storia utente da questo problema?" "MESSAGE": "Sei sicuro di voler creare una nuova storia utente da questo problema?"
}, },
"FILTERS": {
"TITLE": "Filtri",
"INPUT_SEARCH_PLACEHOLDER": "Soggetto o referenza",
"TITLE_ACTION_SEARCH": "Cerca",
"ACTION_SAVE_CUSTOM_FILTER": "salva come filtro personalizzato",
"BREADCRUMB": "Filtri",
"TITLE_BREADCRUMB": "Filtri",
"CATEGORIES": {
"TYPE": "Tipo",
"STATUS": "Stato",
"SEVERITY": "Gravità",
"PRIORITIES": "priorità",
"TAGS": "Tag",
"ASSIGNED_TO": "Assegna a",
"CREATED_BY": "Creato da",
"CUSTOM_FILTERS": "Filtri personalizzati"
},
"CONFIRM_DELETE": {
"TITLE": "Elimina il filtro personalizzato",
"MESSAGE": "Il filtro personalizzato '{{customFilterName}}'"
}
},
"TABLE": { "TABLE": {
"COLUMNS": { "COLUMNS": {
"TYPE": "Tipo", "TYPE": "Tipo",
@ -1316,6 +1436,7 @@
"SEARCH": { "SEARCH": {
"PAGE_TITLE": "Cerca - {{projectName}}", "PAGE_TITLE": "Cerca - {{projectName}}",
"PAGE_DESCRIPTION": "Cerca storie utenti, problemi, compiti o pagine wiki, all'interno del progetto {{projectName}}: {{projectDescription}}", "PAGE_DESCRIPTION": "Cerca storie utenti, problemi, compiti o pagine wiki, all'interno del progetto {{projectName}}: {{projectDescription}}",
"FILTER_EPICS": "Epics",
"FILTER_USER_STORIES": "Storie Utente", "FILTER_USER_STORIES": "Storie Utente",
"FILTER_ISSUES": "problemi", "FILTER_ISSUES": "problemi",
"FILTER_TASKS": "Compiti", "FILTER_TASKS": "Compiti",
@ -1417,13 +1538,24 @@
"DELETE_LIGHTBOX_TITLE": "Elimina Pagina Wiki", "DELETE_LIGHTBOX_TITLE": "Elimina Pagina Wiki",
"DELETE_LINK_TITLE": "Delete Wiki link", "DELETE_LINK_TITLE": "Delete Wiki link",
"NAVIGATION": { "NAVIGATION": {
"SECTION_NAME": "Link", "HOME": "Main Page",
"ACTION_ADD_LINK": "Aggiungi link" "SECTION_NAME": "BOOKMARKS",
"ACTION_ADD_LINK": "Add bookmark",
"ALL_PAGES": "All wiki pages"
}, },
"SUMMARY": { "SUMMARY": {
"TIMES_EDITED": "tempo <br />modificato", "TIMES_EDITED": "tempo <br />modificato",
"LAST_EDIT": "<br /> ultima modifica", "LAST_EDIT": "<br /> ultima modifica",
"LAST_MODIFICATION": "ultima modifica" "LAST_MODIFICATION": "ultima modifica"
},
"SECTION_PAGES_LIST": "All pages",
"PAGES_LIST_COLUMNS": {
"TITLE": "Title",
"EDITIONS": "Editions",
"CREATED": "Creato",
"MODIFIED": "Modified",
"CREATOR": "Creator",
"LAST_MODIFIER": "Last modifier"
} }
}, },
"HINTS": { "HINTS": {
@ -1447,6 +1579,8 @@
"TASK_CREATED_WITH_US": "{{username}} ha creato un nuovo compito {{obj_name}} in {{project_name}} che appartiene alla storia utente {{us_name}}", "TASK_CREATED_WITH_US": "{{username}} ha creato un nuovo compito {{obj_name}} in {{project_name}} che appartiene alla storia utente {{us_name}}",
"WIKI_CREATED": "{{username}} ha creato una nuova pagina wiki {{obj_name}} in {{project_name}}", "WIKI_CREATED": "{{username}} ha creato una nuova pagina wiki {{obj_name}} in {{project_name}}",
"MILESTONE_CREATED": "{{username}} ha creato un nuovo sprint {{obj_name}} in {{project_name}}", "MILESTONE_CREATED": "{{username}} ha creato un nuovo sprint {{obj_name}} in {{project_name}}",
"EPIC_CREATED": "{{username}} has created a new epic {{obj_name}} in {{project_name}}",
"EPIC_RELATED_USERSTORY_CREATED": "{{username}} has related the userstory {{related_us_name}} to the epic {{epic_name}} in {{project_name}}",
"NEW_PROJECT": "{{username}} ha creato il progetto {{project_name}}", "NEW_PROJECT": "{{username}} ha creato il progetto {{project_name}}",
"MILESTONE_UPDATED": "{{username}} ha aggiornato lo sprint {{obj_name}}", "MILESTONE_UPDATED": "{{username}} ha aggiornato lo sprint {{obj_name}}",
"US_UPDATED": "{{username}} ha aggiornato l'attributo \"{{field_name}}\" alla storia utente {{obj_name}}", "US_UPDATED": "{{username}} ha aggiornato l'attributo \"{{field_name}}\" alla storia utente {{obj_name}}",
@ -1459,9 +1593,13 @@
"TASK_UPDATED_WITH_US": "{{username}} ha aggiornato l'attributo \"{{field_name}}\" del compito {{obj_name}} che appartiene alla storia utente {{us_name}}", "TASK_UPDATED_WITH_US": "{{username}} ha aggiornato l'attributo \"{{field_name}}\" del compito {{obj_name}} che appartiene alla storia utente {{us_name}}",
"TASK_UPDATED_WITH_US_NEW_VALUE": "{{username}} ha aggiornato l'attributo \"{{field_name}}\" del compito {{obj_name}} che appartiene alla storia utente {{us_name}} a {{new_value}}", "TASK_UPDATED_WITH_US_NEW_VALUE": "{{username}} ha aggiornato l'attributo \"{{field_name}}\" del compito {{obj_name}} che appartiene alla storia utente {{us_name}} a {{new_value}}",
"WIKI_UPDATED": "{{username}} ha aggiornato la pagina wiki {{obj_name}}", "WIKI_UPDATED": "{{username}} ha aggiornato la pagina wiki {{obj_name}}",
"EPIC_UPDATED": "{{username}} has updated the attribute \"{{field_name}}\" of the epic {{obj_name}}",
"EPIC_UPDATED_WITH_NEW_VALUE": "{{username}} has updated the attribute \"{{field_name}}\" of the epic {{obj_name}} to {{new_value}}",
"EPIC_UPDATED_WITH_NEW_COLOR": "{{username}} has updated the \"{{field_name}}\" of the epic {{obj_name}} to <span class=\"new-color\" style=\"background: {{new_value}}\"></span>",
"NEW_COMMENT_US": "{{username}} ha commentato nella storia utente {{obj_name}}", "NEW_COMMENT_US": "{{username}} ha commentato nella storia utente {{obj_name}}",
"NEW_COMMENT_ISSUE": "{{username}} ha commentato nel problema {{obj_name}}", "NEW_COMMENT_ISSUE": "{{username}} ha commentato nel problema {{obj_name}}",
"NEW_COMMENT_TASK": "{{username}} ha commentato nel compito {{obj_name}}", "NEW_COMMENT_TASK": "{{username}} ha commentato nel compito {{obj_name}}",
"NEW_COMMENT_EPIC": "{{username}} has commented in the epic {{obj_name}}",
"NEW_MEMBER": "{{project_name}} ha un nuovo membro", "NEW_MEMBER": "{{project_name}} ha un nuovo membro",
"US_ADDED_MILESTONE": "{{username}} ha aggiunto la storia utente {{obj_name}} a {{sprint_name}}", "US_ADDED_MILESTONE": "{{username}} ha aggiunto la storia utente {{obj_name}} a {{sprint_name}}",
"US_MOVED": "{{username}} ha spostato la storia utente {{obj_name}}", "US_MOVED": "{{username}} ha spostato la storia utente {{obj_name}}",

File diff suppressed because it is too large Load Diff

View File

@ -35,6 +35,8 @@
"ONE_ITEM_LINE": "Eén item per regel...", "ONE_ITEM_LINE": "Eén item per regel...",
"NEW_BULK": "Nieuwe bulk toevoeging", "NEW_BULK": "Nieuwe bulk toevoeging",
"RELATED_TASKS": "Gerelateerde taken", "RELATED_TASKS": "Gerelateerde taken",
"PREVIOUS": "Previous",
"NEXT": "Volgende",
"LOGOUT": "Afmelden", "LOGOUT": "Afmelden",
"EXTERNAL_USER": "een extern gebruiker", "EXTERNAL_USER": "een extern gebruiker",
"GENERIC_ERROR": "Een van onze Oempa Loempa's zegt {{error}}.", "GENERIC_ERROR": "Een van onze Oempa Loempa's zegt {{error}}.",
@ -45,6 +47,11 @@
"CAPSLOCK_WARNING": "Be careful! You are using capital letters in an input field that is case sensitive.", "CAPSLOCK_WARNING": "Be careful! You are using capital letters in an input field that is case sensitive.",
"CONFIRM_CLOSE_EDIT_MODE_TITLE": "Are you sure you want to close the edit mode?", "CONFIRM_CLOSE_EDIT_MODE_TITLE": "Are you sure you want to close the edit mode?",
"CONFIRM_CLOSE_EDIT_MODE_MESSAGE": "Remember that if you close the edit mode without saving all the changes will be lost", "CONFIRM_CLOSE_EDIT_MODE_MESSAGE": "Remember that if you close the edit mode without saving all the changes will be lost",
"RELATED_USERSTORIES": "Related user stories",
"CARD": {
"ASSIGN_TO": "Assign To",
"EDIT": "Edit card"
},
"FORM_ERRORS": { "FORM_ERRORS": {
"DEFAULT_MESSAGE": "Deze waarde lijkt ongeldig te zijn", "DEFAULT_MESSAGE": "Deze waarde lijkt ongeldig te zijn",
"TYPE_EMAIL": "Deze waarde moet een geldig emailadres bevatten", "TYPE_EMAIL": "Deze waarde moet een geldig emailadres bevatten",
@ -115,8 +122,9 @@
"USER_STORY": "User story", "USER_STORY": "User story",
"TASK": "Taak", "TASK": "Taak",
"ISSUE": "Issue", "ISSUE": "Issue",
"EPIC": "Epic",
"TAGS": { "TAGS": {
"PLACEHOLDER": "Ik ben 'm! Tag me...", "PLACEHOLDER": "Enter tag",
"DELETE": "Verwijder tag", "DELETE": "Verwijder tag",
"ADD": "Tag tovoegen" "ADD": "Tag tovoegen"
}, },
@ -193,12 +201,29 @@
"CONFIRM_DELETE": "Remeber that all values in this custom field will be deleted.\n Are you sure you want to continue?" "CONFIRM_DELETE": "Remeber that all values in this custom field will be deleted.\n Are you sure you want to continue?"
}, },
"FILTERS": { "FILTERS": {
"TITLE": "filters", "TITLE": "Filters",
"INPUT_PLACEHOLDER": "Onderwerp of referentie", "INPUT_PLACEHOLDER": "Onderwerp of referentie",
"TITLE_ACTION_FILTER_BUTTON": "zoek", "TITLE_ACTION_FILTER_BUTTON": "zoek",
"BREADCRUMB_TITLE": "terug naar categorieën", "INPUT_SEARCH_PLACEHOLDER": "Onderwerp of ref.",
"BREADCRUMB_FILTERS": "Filters", "TITLE_ACTION_SEARCH": "Zoek",
"BREADCRUMB_STATUS": "status" "ACTION_SAVE_CUSTOM_FILTER": "Als eigen filter opslaan",
"PLACEHOLDER_FILTER_NAME": "Geef de filternaam in en druk op enter",
"APPLIED_FILTERS_NUM": "filters applied",
"CATEGORIES": {
"TYPE": "Type",
"STATUS": "Status",
"SEVERITY": "Ernst",
"PRIORITIES": "Prioriteit",
"TAGS": "Tags",
"ASSIGNED_TO": "Toegewezen aan",
"CREATED_BY": "Aangemaakt door",
"CUSTOM_FILTERS": "Eigen filters",
"EPIC": "Epic"
},
"CONFIRM_DELETE": {
"TITLE": "Verwijder eigen filter",
"MESSAGE": "de eigen filter '{{customFilterName}}'"
}
}, },
"WYSIWYG": { "WYSIWYG": {
"H1_BUTTON": "Eerste niveau heading", "H1_BUTTON": "Eerste niveau heading",
@ -228,9 +253,18 @@
"PREVIEW_BUTTON": "Voorbeeld", "PREVIEW_BUTTON": "Voorbeeld",
"EDIT_BUTTON": "Bewerk", "EDIT_BUTTON": "Bewerk",
"ATTACH_FILE_HELP": "Attach files by dragging & dropping on the textarea above.", "ATTACH_FILE_HELP": "Attach files by dragging & dropping on the textarea above.",
"ATTACH_FILE_HELP_SAVE_FIRST": "Save first before if you want to attach files by dragging & dropping on the textarea above.",
"MARKDOWN_HELP": "Markdown syntax help" "MARKDOWN_HELP": "Markdown syntax help"
}, },
"PERMISIONS_CATEGORIES": { "PERMISIONS_CATEGORIES": {
"EPICS": {
"NAME": "Epics",
"VIEW_EPICS": "View epics",
"ADD_EPICS": "Add epics",
"MODIFY_EPICS": "Modify epics",
"COMMENT_EPICS": "Comment epics",
"DELETE_EPICS": "Delete epics"
},
"SPRINTS": { "SPRINTS": {
"NAME": "Sprints", "NAME": "Sprints",
"VIEW_SPRINTS": "Sprints bekijken", "VIEW_SPRINTS": "Sprints bekijken",
@ -243,6 +277,7 @@
"VIEW_USER_STORIES": "Bekijk user stories", "VIEW_USER_STORIES": "Bekijk user stories",
"ADD_USER_STORIES": "User stories toevoegen", "ADD_USER_STORIES": "User stories toevoegen",
"MODIFY_USER_STORIES": "user stories bewerken", "MODIFY_USER_STORIES": "user stories bewerken",
"COMMENT_USER_STORIES": "Comment user stories",
"DELETE_USER_STORIES": "Verwijderd user stories" "DELETE_USER_STORIES": "Verwijderd user stories"
}, },
"TASKS": { "TASKS": {
@ -250,6 +285,7 @@
"VIEW_TASKS": "Bekijk taken", "VIEW_TASKS": "Bekijk taken",
"ADD_TASKS": "Taak toevoegen", "ADD_TASKS": "Taak toevoegen",
"MODIFY_TASKS": "Bewerk taken", "MODIFY_TASKS": "Bewerk taken",
"COMMENT_TASKS": "Comment tasks",
"DELETE_TASKS": "Verwijder taken" "DELETE_TASKS": "Verwijder taken"
}, },
"ISSUES": { "ISSUES": {
@ -257,6 +293,7 @@
"VIEW_ISSUES": "Bekijk issues", "VIEW_ISSUES": "Bekijk issues",
"ADD_ISSUES": "Issues toevoegen", "ADD_ISSUES": "Issues toevoegen",
"MODIFY_ISSUES": "Bewerk issues", "MODIFY_ISSUES": "Bewerk issues",
"COMMENT_ISSUES": "Comment issues",
"DELETE_ISSUES": "Issues verwijderen" "DELETE_ISSUES": "Issues verwijderen"
}, },
"WIKI": { "WIKI": {
@ -366,6 +403,41 @@
"WATCHING_SECTION": "Volgers", "WATCHING_SECTION": "Volgers",
"DASHBOARD": "Projects Dashboard" "DASHBOARD": "Projects Dashboard"
}, },
"EPICS": {
"TITLE": "EPICS",
"SECTION_NAME": "Epics",
"EPIC": "EPIC",
"PAGE_TITLE": "Epics - {{projectName}}",
"PAGE_DESCRIPTION": "The epics list of the project {{projectName}}: {{projectDescription}}",
"DASHBOARD": {
"ADD": "+ ADD EPIC",
"UNASSIGNED": "Niet toegewezen"
},
"EMPTY": {
"TITLE": "It looks like there aren't any epics yet",
"EXPLANATION": "Epics are items at a higher level that encompass user stories.<br />Epics are at the top of the hierarchy and can be used to group user stories together.",
"HELP": "Learn more about epics"
},
"TABLE": {
"VOTES": "Stemmen",
"NAME": "Naam",
"PROJECT": "Project",
"SPRINT": "Sprint",
"ASSIGNED_TO": "Assigned",
"STATUS": "Status",
"PROGRESS": "Progress",
"VIEW_OPTIONS": "View options"
},
"CREATE": {
"TITLE": "New Epic",
"PLACEHOLDER_DESCRIPTION": "Please add descriptive text to help others better understand this epic",
"TEAM_REQUIREMENT": "Team requirement",
"CLIENT_REQUIREMENT": "Client requirement",
"BLOCKED": "Geblokkeerd",
"BLOCKED_NOTE_PLACEHOLDER": "Why is this epic blocked?",
"CREATE_EPIC": "Create epic"
}
},
"PROJECTS": { "PROJECTS": {
"PAGE_TITLE": "Mijn projecten - Taiga", "PAGE_TITLE": "Mijn projecten - Taiga",
"PAGE_DESCRIPTION": "Een lijst met al jouw projecten, je kunt deze herodenen of een nieuwe aanmaken.", "PAGE_DESCRIPTION": "Een lijst met al jouw projecten, je kunt deze herodenen of een nieuwe aanmaken.",
@ -402,7 +474,8 @@
"ADMIN": { "ADMIN": {
"COMMON": { "COMMON": {
"TITLE_ACTION_EDIT_VALUE": "Bewerk waarde", "TITLE_ACTION_EDIT_VALUE": "Bewerk waarde",
"TITLE_ACTION_DELETE_VALUE": "Verwijder waarde" "TITLE_ACTION_DELETE_VALUE": "Verwijder waarde",
"TITLE_ACTION_DELETE_TAG": "Verwijder tag"
}, },
"HELP": "Help je hulp nodig? Bekijk onze support pagina!", "HELP": "Help je hulp nodig? Bekijk onze support pagina!",
"PROJECT_DEFAULT_VALUES": { "PROJECT_DEFAULT_VALUES": {
@ -435,6 +508,8 @@
"TITLE": "Modules", "TITLE": "Modules",
"ENABLE": "Inschakelen", "ENABLE": "Inschakelen",
"DISABLE": "Uitschakelen", "DISABLE": "Uitschakelen",
"EPICS": "Epics",
"EPICS_DESCRIPTION": "Visualize and manage the most strategic part of your project",
"BACKLOG": "Backlog", "BACKLOG": "Backlog",
"BACKLOG_DESCRIPTION": "Organiseer je user stories om een duidelijk overzicht van aankomend en geprioritiseerd werk te behouden.", "BACKLOG_DESCRIPTION": "Organiseer je user stories om een duidelijk overzicht van aankomend en geprioritiseerd werk te behouden.",
"NUMBER_SPRINTS": "Expected number of sprints", "NUMBER_SPRINTS": "Expected number of sprints",
@ -497,6 +572,7 @@
"REGENERATE_SUBTITLE": "Je staat op het punt de CSV data toegang url te veranderen. De vorige url zal worden uitgeschakeld. Ben je zeker dat je ermee door wil gaan?" "REGENERATE_SUBTITLE": "Je staat op het punt de CSV data toegang url te veranderen. De vorige url zal worden uitgeschakeld. Ben je zeker dat je ermee door wil gaan?"
}, },
"CSV": { "CSV": {
"SECTION_TITLE_EPIC": "epics reports",
"SECTION_TITLE_US": "user stories rapporten", "SECTION_TITLE_US": "user stories rapporten",
"SECTION_TITLE_TASK": "taak rapporten", "SECTION_TITLE_TASK": "taak rapporten",
"SECTION_TITLE_ISSUE": "Issues rapport", "SECTION_TITLE_ISSUE": "Issues rapport",
@ -509,6 +585,8 @@
"CUSTOM_FIELDS": { "CUSTOM_FIELDS": {
"TITLE": "Eigen velden", "TITLE": "Eigen velden",
"SUBTITLE": "Specifieer de aangepaste velden voor je user stories, taken en issues", "SUBTITLE": "Specifieer de aangepaste velden voor je user stories, taken en issues",
"EPIC_DESCRIPTION": "Epics custom fields",
"EPIC_ADD": "Add a custom field in epics",
"US_DESCRIPTION": "Eigen velden user stories", "US_DESCRIPTION": "Eigen velden user stories",
"US_ADD": "Voeg eigen velden toe in user stories", "US_ADD": "Voeg eigen velden toe in user stories",
"TASK_DESCRIPTION": "Eigen velden taken", "TASK_DESCRIPTION": "Eigen velden taken",
@ -546,7 +624,8 @@
"PROJECT_VALUES_STATUS": { "PROJECT_VALUES_STATUS": {
"TITLE": "Status", "TITLE": "Status",
"SUBTITLE": "Specifieer de statussen waar je user stories, taken en issues door zullen gaan", "SUBTITLE": "Specifieer de statussen waar je user stories, taken en issues door zullen gaan",
"US_TITLE": "US statussen", "EPIC_TITLE": "Epic Statuses",
"US_TITLE": "User Story Statuses",
"TASK_TITLE": "Taak statussen", "TASK_TITLE": "Taak statussen",
"ISSUE_TITLE": "Issue statussen" "ISSUE_TITLE": "Issue statussen"
}, },
@ -556,6 +635,17 @@
"ISSUE_TITLE": "Issues types", "ISSUE_TITLE": "Issues types",
"ACTION_ADD": "Voeg nieuwe {{objName}} toe" "ACTION_ADD": "Voeg nieuwe {{objName}} toe"
}, },
"PROJECT_VALUES_TAGS": {
"TITLE": "Tags",
"SUBTITLE": "View and edit the color of your tags",
"EMPTY": "Currently there are no tags",
"EMPTY_SEARCH": "It looks like nothing was found with your search criteria",
"ACTION_ADD": "Tag tovoegen",
"NEW_TAG": "New tag",
"MIXING_HELP_TEXT": "Select the tags that you want to merge",
"MIXING_MERGE": "Merge Tags",
"SELECTED": "Selected"
},
"ROLES": { "ROLES": {
"PAGE_TITLE": "Rollen - {{projectName}}", "PAGE_TITLE": "Rollen - {{projectName}}",
"WARNING_NO_ROLE": "Wees voorzichtig, geen enkele rol in je project zal de puntenwaarde van een user story kunnen estimeren", "WARNING_NO_ROLE": "Wees voorzichtig, geen enkele rol in je project zal de puntenwaarde van een user story kunnen estimeren",
@ -588,6 +678,10 @@
"SECTION_NAME": "Github", "SECTION_NAME": "Github",
"PAGE_TITLE": "Github - {{projectName}}" "PAGE_TITLE": "Github - {{projectName}}"
}, },
"GOGS": {
"SECTION_NAME": "Gogs",
"PAGE_TITLE": "Gogs - {{projectName}}"
},
"WEBHOOKS": { "WEBHOOKS": {
"PAGE_TITLE": "Webhooks - {{projectName}}", "PAGE_TITLE": "Webhooks - {{projectName}}",
"SECTION_NAME": "Webhooks", "SECTION_NAME": "Webhooks",
@ -643,13 +737,14 @@
"DEFAULT_DELETE_MESSAGE": "de uitnodiging naar {{email}}" "DEFAULT_DELETE_MESSAGE": "de uitnodiging naar {{email}}"
}, },
"DEFAULT_VALUES": { "DEFAULT_VALUES": {
"LABEL_EPIC_STATUS": "Default value for epic status selector",
"LABEL_US_STATUS": "Default value for user story status selector",
"LABEL_POINTS": "Standaard waarde voor punten selectie", "LABEL_POINTS": "Standaard waarde voor punten selectie",
"LABEL_US": "Standaard waarde voor US status selectie",
"LABEL_TASK_STATUS": "Standaard waarde voor taak status selectie", "LABEL_TASK_STATUS": "Standaard waarde voor taak status selectie",
"LABEL_PRIORITY": "Standaard waarde voor prioriteit selectie",
"LABEL_SEVERITY": "Standaard waarde voor ernst selectie",
"LABEL_ISSUE_TYPE": "Standaard waarde voor issue type selectie", "LABEL_ISSUE_TYPE": "Standaard waarde voor issue type selectie",
"LABEL_ISSUE_STATUS": "Standaard waarde voor issue status selectie" "LABEL_ISSUE_STATUS": "Standaard waarde voor issue status selectie",
"LABEL_PRIORITY": "Standaard waarde voor prioriteit selectie",
"LABEL_SEVERITY": "Standaard waarde voor ernst selectie"
}, },
"STATUS": { "STATUS": {
"PLACEHOLDER_WRITE_STATUS_NAME": "Geef een naam voor de nieuwe status" "PLACEHOLDER_WRITE_STATUS_NAME": "Geef een naam voor de nieuwe status"
@ -681,7 +776,8 @@
"PRIORITIES": "Prioriteiten", "PRIORITIES": "Prioriteiten",
"SEVERITIES": "Ernst", "SEVERITIES": "Ernst",
"TYPES": "Types", "TYPES": "Types",
"CUSTOM_FIELDS": "Eigen velden" "CUSTOM_FIELDS": "Eigen velden",
"TAGS": "Tags"
}, },
"SUBMENU_PROJECT_PROFILE": { "SUBMENU_PROJECT_PROFILE": {
"TITLE": "Project profiel" "TITLE": "Project profiel"
@ -751,6 +847,8 @@
"FILTER_TYPE_ALL_TITLE": "Alles weergeven", "FILTER_TYPE_ALL_TITLE": "Alles weergeven",
"FILTER_TYPE_PROJECTS": "Projecten", "FILTER_TYPE_PROJECTS": "Projecten",
"FILTER_TYPE_PROJECT_TITLES": "Enkel projecten weergeven", "FILTER_TYPE_PROJECT_TITLES": "Enkel projecten weergeven",
"FILTER_TYPE_EPICS": "Epics",
"FILTER_TYPE_EPIC_TITLES": "Show only epics",
"FILTER_TYPE_USER_STORIES": "Verhalen", "FILTER_TYPE_USER_STORIES": "Verhalen",
"FILTER_TYPE_USER_STORIES_TITLES": "Enkel verhalen van gebruikers weergeven", "FILTER_TYPE_USER_STORIES_TITLES": "Enkel verhalen van gebruikers weergeven",
"FILTER_TYPE_TASKS": "Taken", "FILTER_TYPE_TASKS": "Taken",
@ -950,8 +1048,8 @@
"CREATE_MEMBER": { "CREATE_MEMBER": {
"PLACEHOLDER_INVITATION_TEXT": "(Optioneel) Voeg een gepersonaliseerd bericht toe aan je uitnodiging. Vertel iets leuks aan je nieuwe leden ;-)", "PLACEHOLDER_INVITATION_TEXT": "(Optioneel) Voeg een gepersonaliseerd bericht toe aan je uitnodiging. Vertel iets leuks aan je nieuwe leden ;-)",
"PLACEHOLDER_TYPE_EMAIL": "Type en E-mail", "PLACEHOLDER_TYPE_EMAIL": "Type en E-mail",
"LIMIT_USERS_WARNING_MESSAGE_FOR_OWNER": "Unfortunately, this project can't have more than <strong>{{maxMembers}}</strong> members.<br> If you would like to increase the current limit, please contact the administrator.", "LIMIT_USERS_WARNING_MESSAGE_FOR_OWNER": "You are about to reach the maximum number of members allowed for this project, <strong>{{maxMembers}}</strong> members. If you would like to increase the current limit, please contact the administrator.",
"LIMIT_USERS_WARNING_MESSAGE": "Unfortunately, this project can't have more than <strong>{{maxMembers}}</strong> members." "LIMIT_USERS_WARNING_MESSAGE": "You are about to reach the maximum number of members allowed for this project, <strong>{{maxMembers}}</strong> members."
}, },
"LEAVE_PROJECT_WARNING": { "LEAVE_PROJECT_WARNING": {
"TITLE": "Unfortunately, this project can't be left without an owner", "TITLE": "Unfortunately, this project can't be left without an owner",
@ -970,10 +1068,30 @@
"BUTTON": "Ask this project member to become the new project owner" "BUTTON": "Ask this project member to become the new project owner"
} }
}, },
"EPIC": {
"PAGE_TITLE": "{{epicSubject}} - Epic {{epicRef}} - {{projectName}}",
"PAGE_DESCRIPTION": "Status: {{epicStatus }}. Description: {{epicDescription}}",
"SECTION_NAME": "Epic",
"TITLE_LIGHTBOX_UNLINK_RELATED_USERSTORY": "Unlink related userstory",
"MSG_LIGHTBOX_UNLINK_RELATED_USERSTORY": "It will delete the link to the related userstory '{{subject}}'",
"ERROR_UNLINK_RELATED_USERSTORY": "We have not been able to unlink: {{errorMessage}}",
"CREATE_RELATED_USERSTORIES": "Create a relationship with",
"NEW_USERSTORY": "Nieuwe user story",
"EXISTING_USERSTORY": "Existing user story",
"CHOOSE_PROJECT_FOR_CREATION": "What's the project?",
"SUBJECT": "Onderwerp",
"SUBJECT_BULK_MODE": "Subject (bulk insert)",
"CHOOSE_PROJECT_FROM": "What's the project?",
"CHOOSE_USERSTORY": "What's the user story?",
"NO_USERSTORIES": "This project has no User Stories yet. Please select another project.",
"FILTER_USERSTORIES": "Filter user stories",
"LIGHTBOX_TITLE_BLOKING_EPIC": "Blocking epic",
"ACTION_DELETE": "Delete epic"
},
"US": { "US": {
"PAGE_TITLE": "{{userStorySubject}} - User Story {{userStoryRef}} - {{projectName}}", "PAGE_TITLE": "{{userStorySubject}} - User Story {{userStoryRef}} - {{projectName}}",
"PAGE_DESCRIPTION": "Status: {{userStoryStatus }}. Voltooid {{userStoryProgressPercentage}}% ({{userStoryClosedTasks}} van {{userStoryTotalTasks}} taken gesloten). Punten: {{userStoryPoints}}. Omschrijving: {{userStoryDescription}}", "PAGE_DESCRIPTION": "Status: {{userStoryStatus }}. Voltooid {{userStoryProgressPercentage}}% ({{userStoryClosedTasks}} van {{userStoryTotalTasks}} taken gesloten). Punten: {{userStoryPoints}}. Omschrijving: {{userStoryDescription}}",
"SECTION_NAME": "User story details", "SECTION_NAME": "User story",
"LINK_TASKBOARD": "Taakbord", "LINK_TASKBOARD": "Taakbord",
"TITLE_LINK_TASKBOARD": "Ga naar het dashboard", "TITLE_LINK_TASKBOARD": "Ga naar het dashboard",
"TOTAL_POINTS": "totaal aantal punten", "TOTAL_POINTS": "totaal aantal punten",
@ -984,14 +1102,23 @@
"EXTERNAL_REFERENCE": "Deze US is aangemaakt vanaf", "EXTERNAL_REFERENCE": "Deze US is aangemaakt vanaf",
"GO_TO_EXTERNAL_REFERENCE": "Ga naar bron", "GO_TO_EXTERNAL_REFERENCE": "Ga naar bron",
"BLOCKED": "Deze user story is geblokkeerd", "BLOCKED": "Deze user story is geblokkeerd",
"PREVIOUS": "Vorige user story",
"NEXT": "volgende user story",
"TITLE_DELETE_ACTION": "Verwijder user story", "TITLE_DELETE_ACTION": "Verwijder user story",
"LIGHTBOX_TITLE_BLOKING_US": "User story blokkeren", "LIGHTBOX_TITLE_BLOKING_US": "User story blokkeren",
"TASK_COMPLETED": "{{totalClosedTasks}}/{{totalTasks}} taken afgewerkt", "TASK_COMPLETED": "{{totalClosedTasks}}/{{totalTasks}} taken afgewerkt",
"ASSIGN": "User story toewijzen", "ASSIGN": "User story toewijzen",
"NOT_ESTIMATED": "Niet ingeschat", "NOT_ESTIMATED": "Niet ingeschat",
"TOTAL_US_POINTS": "Totaal US punten", "TOTAL_US_POINTS": "Totaal US punten",
"TRIBE": {
"PUBLISH": "Publish as Gig in Taiga Tribe",
"PUBLISH_INFO": "More info",
"PUBLISH_TITLE": "More info on publishing in Taiga Tribe",
"PUBLISHED_AS_GIG": "Story published as Gig in Taiga Tribe",
"EDIT_LINK": "Edit link",
"CLOSE": "Close",
"SYNCHRONIZE_LINK": "synchronize with Taiga Tribe",
"PUBLISH_MORE_INFO_TITLE": "Do you need somebody for this task?",
"PUBLISH_MORE_INFO_TEXT": "<p>If you need help with a particular piece of work you can easily create gigs on<a href='taigatribe.com' title='Taiga Tribe'> Taiga Tribe </a> and receive help from all over the world. You will be able to control and manage the gig enjoying a great community eager to contribute.</p><p><a href='taigatribe.com' title='Taiga Tribe'> TaigaTribe </a> was born as a Taiga sibling. Both platforms can live separately but we believe that there is much power in using them combined so we are making sure the integration works like a charm.</p>"
},
"FIELDS": { "FIELDS": {
"TEAM_REQUIREMENT": "Eisen team", "TEAM_REQUIREMENT": "Eisen team",
"CLIENT_REQUIREMENT": "Requirement van de klant", "CLIENT_REQUIREMENT": "Requirement van de klant",
@ -999,28 +1126,47 @@
} }
}, },
"COMMENTS": { "COMMENTS": {
"DELETED_INFO": "Opmerking verwijderd door {{user}} op {{date}}", "DELETED_INFO": "Comment deleted by {{user}}",
"TITLE": "Reacties", "TITLE": "Reacties",
"COMMENTS_COUNT": "{{comments}} Comments",
"ORDER": "Order",
"OLDER_FIRST": "Older first",
"RECENT_FIRST": "Recent first",
"COMMENT": "Reageer", "COMMENT": "Reageer",
"EDIT_COMMENT": "Edit comment",
"EDITED_COMMENT": "Edited:",
"SHOW_HISTORY": "View historic",
"TYPE_NEW_COMMENT": "Type hier nieuw commentaar", "TYPE_NEW_COMMENT": "Type hier nieuw commentaar",
"SHOW_DELETED": "Toon verwijderd commentaar", "SHOW_DELETED": "Toon verwijderd commentaar",
"HIDE_DELETED": "Verberg verwijderde opmerkingen", "HIDE_DELETED": "Verberg verwijderde opmerkingen",
"DELETE": "Delete comment", "DELETE": "Delete comment",
"RESTORE": "Opmerking herstellen" "RESTORE": "Opmerking herstellen",
"HISTORY": {
"TITLE": "Activiteit"
}
}, },
"ACTIVITY": { "ACTIVITY": {
"SHOW_ACTIVITY": "Toon activiteit", "SHOW_ACTIVITY": "Toon activiteit",
"DATETIME": "DD MMM YYYY HH:mm", "DATETIME": "DD MMM YYYY HH:mm",
"SHOW_MORE": "+ Toon vorige items ({{showMore}} meer)", "SHOW_MORE": "+ Toon vorige items ({{showMore}} meer)",
"TITLE": "Activiteit", "TITLE": "Activiteit",
"ACTIVITIES_COUNT": "{{activities}} Activities",
"REMOVED": "verwijderd", "REMOVED": "verwijderd",
"ADDED": "toegevoegd", "ADDED": "toegevoegd",
"US_POINTS": "US punten ({{name}})", "TAGS_ADDED": "tags added:",
"NEW_ATTACHMENT": "Nieuwe bijlage", "TAGS_REMOVED": "tags removed:",
"DELETED_ATTACHMENT": "verwijderd bijlage", "US_POINTS": "{{role}} points",
"UPDATED_ATTACHMENT": "bijlage {{filename}} bijgewerkt", "NEW_ATTACHMENT": "new attachment:",
"DELETED_CUSTOM_ATTRIBUTE": "eigen attribuut verwijderen", "DELETED_ATTACHMENT": "deleted attachment:",
"UPDATED_ATTACHMENT": "updated attachment ({{filename}}):",
"CREATED_CUSTOM_ATTRIBUTE": "created custom attribute",
"UPDATED_CUSTOM_ATTRIBUTE": "updated custom attribute",
"SIZE_CHANGE": "{size, plural, one{één verandering} other{# veranderingen}} gemaakt", "SIZE_CHANGE": "{size, plural, one{één verandering} other{# veranderingen}} gemaakt",
"BECAME_DEPRECATED": "became deprecated",
"BECAME_UNDEPRECATED": "became undeprecated",
"TEAM_REQUIREMENT": "Eisen team",
"CLIENT_REQUIREMENT": "Requirement van de klant",
"BLOCKED": "Geblokkeerd",
"VALUES": { "VALUES": {
"YES": "ja", "YES": "ja",
"NO": "nee", "NO": "nee",
@ -1052,12 +1198,14 @@
"TAGS": "tags", "TAGS": "tags",
"ATTACHMENTS": "bijlagen", "ATTACHMENTS": "bijlagen",
"IS_DEPRECATED": "is verourderd", "IS_DEPRECATED": "is verourderd",
"IS_NOT_DEPRECATED": "is not deprecated",
"ORDER": "volgorde", "ORDER": "volgorde",
"BACKLOG_ORDER": "backlog volgorde", "BACKLOG_ORDER": "backlog volgorde",
"SPRINT_ORDER": "sprint volgorde", "SPRINT_ORDER": "sprint volgorde",
"KANBAN_ORDER": "kanban volgorde", "KANBAN_ORDER": "kanban volgorde",
"TASKBOARD_ORDER": "taakbord volgorde", "TASKBOARD_ORDER": "taakbord volgorde",
"US_ORDER": "us volgorde" "US_ORDER": "us volgorde",
"COLOR": "kleur"
} }
}, },
"BACKLOG": { "BACKLOG": {
@ -1109,7 +1257,8 @@
"CLOSED_TASKS": "gesloten<br/>taken", "CLOSED_TASKS": "gesloten<br/>taken",
"IOCAINE_DOSES": "iocaine<br />dosissen", "IOCAINE_DOSES": "iocaine<br />dosissen",
"SHOW_STATISTICS_TITLE": "Toon statistieken", "SHOW_STATISTICS_TITLE": "Toon statistieken",
"TOGGLE_BAKLOG_GRAPH": "Toon/Verstop burndown grafiek" "TOGGLE_BAKLOG_GRAPH": "Toon/Verstop burndown grafiek",
"POINTS_PER_ROLE": "Points per role"
}, },
"SUMMARY": { "SUMMARY": {
"PROJECT_POINTS": "project<br/>punten", "PROJECT_POINTS": "project<br/>punten",
@ -1122,9 +1271,7 @@
"TITLE": "Filters", "TITLE": "Filters",
"REMOVE": "Filters verwijderd", "REMOVE": "Filters verwijderd",
"HIDE": "Filters verbergen", "HIDE": "Filters verbergen",
"SHOW": "Toon filters", "SHOW": "Toon filters"
"FILTER_CATEGORY_STATUS": "Status",
"FILTER_CATEGORY_TAGS": "Tags"
}, },
"SPRINTS": { "SPRINTS": {
"TITLE": "SPRINTS", "TITLE": "SPRINTS",
@ -1179,7 +1326,7 @@
"TASK": { "TASK": {
"PAGE_TITLE": "{{taskSubject}} - Taak {{taskRef}} - {{projectName}}", "PAGE_TITLE": "{{taskSubject}} - Taak {{taskRef}} - {{projectName}}",
"PAGE_DESCRIPTION": "Status: {{taskStatus }}. Omschrijving: {{taskDescription}}", "PAGE_DESCRIPTION": "Status: {{taskStatus }}. Omschrijving: {{taskDescription}}",
"SECTION_NAME": "Taak details", "SECTION_NAME": "Taak",
"LINK_TASKBOARD": "Taakbord", "LINK_TASKBOARD": "Taakbord",
"TITLE_LINK_TASKBOARD": "Ga naar het taakbord", "TITLE_LINK_TASKBOARD": "Ga naar het taakbord",
"PLACEHOLDER_SUBJECT": "Type het nieuwe onderwerp voor de taak", "PLACEHOLDER_SUBJECT": "Type het nieuwe onderwerp voor de taak",
@ -1189,8 +1336,6 @@
"ORIGIN_US": "Deze taak werd aangemaakt vanaf", "ORIGIN_US": "Deze taak werd aangemaakt vanaf",
"TITLE_LINK_GO_ORIGIN": "Ga naar user story", "TITLE_LINK_GO_ORIGIN": "Ga naar user story",
"BLOCKED": "Deze taak is geblokkeerd", "BLOCKED": "Deze taak is geblokkeerd",
"PREVIOUS": "vorige taak",
"NEXT": "volgende taak",
"TITLE_DELETE_ACTION": "Verwijder taak", "TITLE_DELETE_ACTION": "Verwijder taak",
"LIGHTBOX_TITLE_BLOKING_TASK": "Blokkerende taak", "LIGHTBOX_TITLE_BLOKING_TASK": "Blokkerende taak",
"FIELDS": { "FIELDS": {
@ -1228,16 +1373,13 @@
"PAGE_TITLE": "Issues - {{projectName}}", "PAGE_TITLE": "Issues - {{projectName}}",
"PAGE_DESCRIPTION": "Het issue lijst overzicht van het project {{projectName}}: {{projectDescription}}", "PAGE_DESCRIPTION": "Het issue lijst overzicht van het project {{projectName}}: {{projectDescription}}",
"LIST_SECTION_NAME": "Issues", "LIST_SECTION_NAME": "Issues",
"SECTION_NAME": "Issue details", "SECTION_NAME": "Issue",
"ACTION_NEW_ISSUE": "+ nieuw probleem", "ACTION_NEW_ISSUE": "+ nieuw probleem",
"ACTION_PROMOTE_TO_US": "Promoveer tot User Story", "ACTION_PROMOTE_TO_US": "Promoveer tot User Story",
"PLACEHOLDER_FILTER_NAME": "Geef de filternaam in en druk op enter",
"PROMOTED": "Dit issue is gepromoveerd tot US:", "PROMOTED": "Dit issue is gepromoveerd tot US:",
"EXTERNAL_REFERENCE": "Dit issue is aangemaakt vanaf", "EXTERNAL_REFERENCE": "Dit issue is aangemaakt vanaf",
"GO_TO_EXTERNAL_REFERENCE": "Ga naar bron", "GO_TO_EXTERNAL_REFERENCE": "Ga naar bron",
"BLOCKED": "Dit issue is geblokkeerd", "BLOCKED": "Dit issue is geblokkeerd",
"TITLE_PREVIOUS_ISSUE": "vorig issue",
"TITLE_NEXT_ISSUE": "volgend issue",
"ACTION_DELETE": "Verwijderd issue", "ACTION_DELETE": "Verwijderd issue",
"LIGHTBOX_TITLE_BLOKING_ISSUE": "Blokkerend issue", "LIGHTBOX_TITLE_BLOKING_ISSUE": "Blokkerend issue",
"FIELDS": { "FIELDS": {
@ -1249,28 +1391,6 @@
"TITLE": "Bevorder dit issue tot een nieuwe user story", "TITLE": "Bevorder dit issue tot een nieuwe user story",
"MESSAGE": "Weet je zeker dat je een nieuw US van dit issue wilt maken?" "MESSAGE": "Weet je zeker dat je een nieuw US van dit issue wilt maken?"
}, },
"FILTERS": {
"TITLE": "Filters",
"INPUT_SEARCH_PLACEHOLDER": "Onderwerp of ref.",
"TITLE_ACTION_SEARCH": "Zoek",
"ACTION_SAVE_CUSTOM_FILTER": "Als eigen filter opslaan",
"BREADCRUMB": "Filters",
"TITLE_BREADCRUMB": "Filters",
"CATEGORIES": {
"TYPE": "Type",
"STATUS": "Status",
"SEVERITY": "Ernst",
"PRIORITIES": "Prioriteiten",
"TAGS": "Tags",
"ASSIGNED_TO": "Toegewezen aan",
"CREATED_BY": "Aangemaakt door",
"CUSTOM_FILTERS": "Eigen filters"
},
"CONFIRM_DELETE": {
"TITLE": "Verwijder eigen filter",
"MESSAGE": "de eigen filter '{{customFilterName}}'"
}
},
"TABLE": { "TABLE": {
"COLUMNS": { "COLUMNS": {
"TYPE": "Type", "TYPE": "Type",
@ -1316,6 +1436,7 @@
"SEARCH": { "SEARCH": {
"PAGE_TITLE": "Zoek - {{projectName}}", "PAGE_TITLE": "Zoek - {{projectName}}",
"PAGE_DESCRIPTION": "Zoek op alles, user stories, issues, taken, wiki pagina's, in het project {{projectName}}: {{projectDescription}}", "PAGE_DESCRIPTION": "Zoek op alles, user stories, issues, taken, wiki pagina's, in het project {{projectName}}: {{projectDescription}}",
"FILTER_EPICS": "Epics",
"FILTER_USER_STORIES": "User Stories", "FILTER_USER_STORIES": "User Stories",
"FILTER_ISSUES": "Issues", "FILTER_ISSUES": "Issues",
"FILTER_TASKS": "Taken", "FILTER_TASKS": "Taken",
@ -1417,13 +1538,24 @@
"DELETE_LIGHTBOX_TITLE": "Verwijderd wiki pagina", "DELETE_LIGHTBOX_TITLE": "Verwijderd wiki pagina",
"DELETE_LINK_TITLE": "Delete Wiki link", "DELETE_LINK_TITLE": "Delete Wiki link",
"NAVIGATION": { "NAVIGATION": {
"SECTION_NAME": "Links", "HOME": "Main Page",
"ACTION_ADD_LINK": "Link toevoegen" "SECTION_NAME": "BOOKMARKS",
"ACTION_ADD_LINK": "Add bookmark",
"ALL_PAGES": "All wiki pages"
}, },
"SUMMARY": { "SUMMARY": {
"TIMES_EDITED": "keer <br/>bewerkt", "TIMES_EDITED": "keer <br/>bewerkt",
"LAST_EDIT": "laatst <br />bewerkt", "LAST_EDIT": "laatst <br />bewerkt",
"LAST_MODIFICATION": "laatste wijziging" "LAST_MODIFICATION": "laatste wijziging"
},
"SECTION_PAGES_LIST": "All pages",
"PAGES_LIST_COLUMNS": {
"TITLE": "Title",
"EDITIONS": "Editions",
"CREATED": "Aangemaakt",
"MODIFIED": "Modified",
"CREATOR": "Creator",
"LAST_MODIFIER": "Last modifier"
} }
}, },
"HINTS": { "HINTS": {
@ -1447,6 +1579,8 @@
"TASK_CREATED_WITH_US": "{{username}} heeft de nieuwe taak {{obj_name}} aangemakt in {{project_name}} die hoort bij de US {{us_name}}", "TASK_CREATED_WITH_US": "{{username}} heeft de nieuwe taak {{obj_name}} aangemakt in {{project_name}} die hoort bij de US {{us_name}}",
"WIKI_CREATED": "{{username}} heeft een nieuwe Wiki-pagina aangemaakt {{obj_name}} in {{project_name}}", "WIKI_CREATED": "{{username}} heeft een nieuwe Wiki-pagina aangemaakt {{obj_name}} in {{project_name}}",
"MILESTONE_CREATED": "{{username}} heeft een nieuwe sprint aangemaakt {{obj_name}} in {{project_name}}", "MILESTONE_CREATED": "{{username}} heeft een nieuwe sprint aangemaakt {{obj_name}} in {{project_name}}",
"EPIC_CREATED": "{{username}} has created a new epic {{obj_name}} in {{project_name}}",
"EPIC_RELATED_USERSTORY_CREATED": "{{username}} has related the userstory {{related_us_name}} to the epic {{epic_name}} in {{project_name}}",
"NEW_PROJECT": "{{username}} heeft een nieuw project aangemaakt {{project_name}}", "NEW_PROJECT": "{{username}} heeft een nieuw project aangemaakt {{project_name}}",
"MILESTONE_UPDATED": "{{username}} heeft de sprint {{obj_name}} bijgewerkt", "MILESTONE_UPDATED": "{{username}} heeft de sprint {{obj_name}} bijgewerkt",
"US_UPDATED": "{{username}} heeft de eigenschap \"{{field_name}}\" van de US {{obj_name}} bijgewerkt", "US_UPDATED": "{{username}} heeft de eigenschap \"{{field_name}}\" van de US {{obj_name}} bijgewerkt",
@ -1459,9 +1593,13 @@
"TASK_UPDATED_WITH_US": "{{username}} heeft de eigenschap \"{{field_name}}\" van de taak {{obj_name}} die behoort tot de US {{us_name}} bijgewerkt", "TASK_UPDATED_WITH_US": "{{username}} heeft de eigenschap \"{{field_name}}\" van de taak {{obj_name}} die behoort tot de US {{us_name}} bijgewerkt",
"TASK_UPDATED_WITH_US_NEW_VALUE": "{{username}} heeft de eigenschap \"{{field_name}}\" van de taak {{obj_name}} die behoort tot de US {{us_name}} gewijzigd naar {{new_value}}", "TASK_UPDATED_WITH_US_NEW_VALUE": "{{username}} heeft de eigenschap \"{{field_name}}\" van de taak {{obj_name}} die behoort tot de US {{us_name}} gewijzigd naar {{new_value}}",
"WIKI_UPDATED": "{{username}} heeft de wiki pagina {{obj_name}} bijgewerkt", "WIKI_UPDATED": "{{username}} heeft de wiki pagina {{obj_name}} bijgewerkt",
"EPIC_UPDATED": "{{username}} has updated the attribute \"{{field_name}}\" of the epic {{obj_name}}",
"EPIC_UPDATED_WITH_NEW_VALUE": "{{username}} has updated the attribute \"{{field_name}}\" of the epic {{obj_name}} to {{new_value}}",
"EPIC_UPDATED_WITH_NEW_COLOR": "{{username}} has updated the \"{{field_name}}\" of the epic {{obj_name}} to <span class=\"new-color\" style=\"background: {{new_value}}\"></span>",
"NEW_COMMENT_US": "{{username}} heeft gereageerd op de US {{obj_name}}", "NEW_COMMENT_US": "{{username}} heeft gereageerd op de US {{obj_name}}",
"NEW_COMMENT_ISSUE": "{{username}} heeft gereageerd op het issue {{obj_name}}", "NEW_COMMENT_ISSUE": "{{username}} heeft gereageerd op het issue {{obj_name}}",
"NEW_COMMENT_TASK": "{{username}} heeft gereageerd op de taak {{obj_name}}", "NEW_COMMENT_TASK": "{{username}} heeft gereageerd op de taak {{obj_name}}",
"NEW_COMMENT_EPIC": "{{username}} has commented in the epic {{obj_name}}",
"NEW_MEMBER": "{{project_name}} heeft een nieuw lid", "NEW_MEMBER": "{{project_name}} heeft een nieuw lid",
"US_ADDED_MILESTONE": "{{username}} heeft de US {{obj_name}} toegevoegd aan {{sprint_name}}", "US_ADDED_MILESTONE": "{{username}} heeft de US {{obj_name}} toegevoegd aan {{sprint_name}}",
"US_MOVED": "{{username}} heeft de user story {{obj_name}} verplaatst", "US_MOVED": "{{username}} heeft de user story {{obj_name}} verplaatst",

View File

@ -19,11 +19,11 @@
"TAG_LINE": "Twoje zwinne, wolne, otwartoźródłowe narzędzie do zarządzania projektem", "TAG_LINE": "Twoje zwinne, wolne, otwartoźródłowe narzędzie do zarządzania projektem",
"TAG_LINE_2": "Pokochaj swój projekt!", "TAG_LINE_2": "Pokochaj swój projekt!",
"BLOCK": "Blokuj", "BLOCK": "Blokuj",
"BLOCK_TITLE": "Block this item for example if it has a dependency that can not be satisfied", "BLOCK_TITLE": "Zablokuj to np. jeżeli posiada zależności, które nie mogą być zrealizowane",
"BLOCKED": "Zablokowane", "BLOCKED": "Zablokowane",
"UNBLOCK": "Odblokuj", "UNBLOCK": "Odblokuj",
"UNBLOCK_TITLE": "Unblock this item", "UNBLOCK_TITLE": "Odblokuj",
"BLOCKED_NOTE": "Why is this blocked?", "BLOCKED_NOTE": "Dlaczego jest zabokowane?",
"BLOCKED_REASON": "Wyjaśnij powód", "BLOCKED_REASON": "Wyjaśnij powód",
"CREATED_BY": "Utworzone przez {{fullDisplayName}}", "CREATED_BY": "Utworzone przez {{fullDisplayName}}",
"FROM": "od", "FROM": "od",
@ -35,6 +35,8 @@
"ONE_ITEM_LINE": "Jedna pozycja na wiersz...", "ONE_ITEM_LINE": "Jedna pozycja na wiersz...",
"NEW_BULK": "Nowe zbiorcze dodawanie", "NEW_BULK": "Nowe zbiorcze dodawanie",
"RELATED_TASKS": "Zadania pokrewne", "RELATED_TASKS": "Zadania pokrewne",
"PREVIOUS": "Previous",
"NEXT": "Następny",
"LOGOUT": "Wyloguj", "LOGOUT": "Wyloguj",
"EXTERNAL_USER": "zewnętrzny użytkownik", "EXTERNAL_USER": "zewnętrzny użytkownik",
"GENERIC_ERROR": "Umpa Lumpa mówi {{error}}.", "GENERIC_ERROR": "Umpa Lumpa mówi {{error}}.",
@ -45,6 +47,11 @@
"CAPSLOCK_WARNING": "Be careful! You are using capital letters in an input field that is case sensitive.", "CAPSLOCK_WARNING": "Be careful! You are using capital letters in an input field that is case sensitive.",
"CONFIRM_CLOSE_EDIT_MODE_TITLE": "Are you sure you want to close the edit mode?", "CONFIRM_CLOSE_EDIT_MODE_TITLE": "Are you sure you want to close the edit mode?",
"CONFIRM_CLOSE_EDIT_MODE_MESSAGE": "Remember that if you close the edit mode without saving all the changes will be lost", "CONFIRM_CLOSE_EDIT_MODE_MESSAGE": "Remember that if you close the edit mode without saving all the changes will be lost",
"RELATED_USERSTORIES": "Related user stories",
"CARD": {
"ASSIGN_TO": "Assign To",
"EDIT": "Edit card"
},
"FORM_ERRORS": { "FORM_ERRORS": {
"DEFAULT_MESSAGE": "Nieprawidłowa wartość", "DEFAULT_MESSAGE": "Nieprawidłowa wartość",
"TYPE_EMAIL": "Podaj prawidłowy adres email.", "TYPE_EMAIL": "Podaj prawidłowy adres email.",
@ -115,8 +122,9 @@
"USER_STORY": "Historyjka użytkownika", "USER_STORY": "Historyjka użytkownika",
"TASK": "Zadania", "TASK": "Zadania",
"ISSUE": "Zgłoszenie", "ISSUE": "Zgłoszenie",
"EPIC": "Epic",
"TAGS": { "TAGS": {
"PLACEHOLDER": "Otaguj mnie!...", "PLACEHOLDER": "Enter tag",
"DELETE": "Usuń tag", "DELETE": "Usuń tag",
"ADD": "Dodaj tag" "ADD": "Dodaj tag"
}, },
@ -193,12 +201,29 @@
"CONFIRM_DELETE": "Remeber that all values in this custom field will be deleted.\n Are you sure you want to continue?" "CONFIRM_DELETE": "Remeber that all values in this custom field will be deleted.\n Are you sure you want to continue?"
}, },
"FILTERS": { "FILTERS": {
"TITLE": "filtry", "TITLE": "Filtry",
"INPUT_PLACEHOLDER": "Temat lub odniesienie", "INPUT_PLACEHOLDER": "Temat lub odniesienie",
"TITLE_ACTION_FILTER_BUTTON": "szukaj", "TITLE_ACTION_FILTER_BUTTON": "szukaj",
"BREADCRUMB_TITLE": "wróć do kategorii", "INPUT_SEARCH_PLACEHOLDER": "Temat lub referencja",
"BREADCRUMB_FILTERS": "Filtry", "TITLE_ACTION_SEARCH": "Szukaj",
"BREADCRUMB_STATUS": "status" "ACTION_SAVE_CUSTOM_FILTER": "zapisz jako filtr niestandardowy",
"PLACEHOLDER_FILTER_NAME": "Wpisz nazwę filtru i kliknij enter",
"APPLIED_FILTERS_NUM": "filters applied",
"CATEGORIES": {
"TYPE": "Typ",
"STATUS": "Statusy",
"SEVERITY": "Ważność",
"PRIORITIES": "Priorytety",
"TAGS": "Tagi",
"ASSIGNED_TO": "Przypisane do",
"CREATED_BY": "Stworzona przez",
"CUSTOM_FILTERS": "Filtry niestandardowe",
"EPIC": "Epic"
},
"CONFIRM_DELETE": {
"TITLE": "Usuń filtr niestandardowy",
"MESSAGE": "filtr niestandardowy '{{customFilterName}}'"
}
}, },
"WYSIWYG": { "WYSIWYG": {
"H1_BUTTON": "Nagłówek pierwszego poziomu", "H1_BUTTON": "Nagłówek pierwszego poziomu",
@ -228,9 +253,18 @@
"PREVIEW_BUTTON": "Podgląd", "PREVIEW_BUTTON": "Podgląd",
"EDIT_BUTTON": "Edycja", "EDIT_BUTTON": "Edycja",
"ATTACH_FILE_HELP": "Attach files by dragging & dropping on the textarea above.", "ATTACH_FILE_HELP": "Attach files by dragging & dropping on the textarea above.",
"ATTACH_FILE_HELP_SAVE_FIRST": "Save first before if you want to attach files by dragging & dropping on the textarea above.",
"MARKDOWN_HELP": "Składnia Markdown pomoc" "MARKDOWN_HELP": "Składnia Markdown pomoc"
}, },
"PERMISIONS_CATEGORIES": { "PERMISIONS_CATEGORIES": {
"EPICS": {
"NAME": "Epics",
"VIEW_EPICS": "View epics",
"ADD_EPICS": "Add epics",
"MODIFY_EPICS": "Modify epics",
"COMMENT_EPICS": "Comment epics",
"DELETE_EPICS": "Delete epics"
},
"SPRINTS": { "SPRINTS": {
"NAME": "Sprinty", "NAME": "Sprinty",
"VIEW_SPRINTS": "Przeglądaj Sprinty", "VIEW_SPRINTS": "Przeglądaj Sprinty",
@ -243,6 +277,7 @@
"VIEW_USER_STORIES": "Przeglądaj historyjki użytkownika", "VIEW_USER_STORIES": "Przeglądaj historyjki użytkownika",
"ADD_USER_STORIES": "Dodawaj historyjki użytkownika", "ADD_USER_STORIES": "Dodawaj historyjki użytkownika",
"MODIFY_USER_STORIES": "Modyfikuj historyjki użytkownika", "MODIFY_USER_STORIES": "Modyfikuj historyjki użytkownika",
"COMMENT_USER_STORIES": "Comment user stories",
"DELETE_USER_STORIES": "Usuwaj historyjki użytkownika" "DELETE_USER_STORIES": "Usuwaj historyjki użytkownika"
}, },
"TASKS": { "TASKS": {
@ -250,6 +285,7 @@
"VIEW_TASKS": "Przeglądaj zadania", "VIEW_TASKS": "Przeglądaj zadania",
"ADD_TASKS": "Dodawaj zadania", "ADD_TASKS": "Dodawaj zadania",
"MODIFY_TASKS": "Modyfikuj zadania", "MODIFY_TASKS": "Modyfikuj zadania",
"COMMENT_TASKS": "Comment tasks",
"DELETE_TASKS": "Usuwaj zadania" "DELETE_TASKS": "Usuwaj zadania"
}, },
"ISSUES": { "ISSUES": {
@ -257,6 +293,7 @@
"VIEW_ISSUES": "Przeglądaj zgłoszenia", "VIEW_ISSUES": "Przeglądaj zgłoszenia",
"ADD_ISSUES": "Dodawaj zgłoszenia", "ADD_ISSUES": "Dodawaj zgłoszenia",
"MODIFY_ISSUES": "Modyfikuj zgłoszenia", "MODIFY_ISSUES": "Modyfikuj zgłoszenia",
"COMMENT_ISSUES": "Comment issues",
"DELETE_ISSUES": "Usuwaj zgłoszenia" "DELETE_ISSUES": "Usuwaj zgłoszenia"
}, },
"WIKI": { "WIKI": {
@ -359,13 +396,48 @@
"HOME": { "HOME": {
"PAGE_TITLE": "Strona główna - Taiga", "PAGE_TITLE": "Strona główna - Taiga",
"PAGE_DESCRIPTION": "Główna strona Taiga, z Twoimi głównymi projektami i wszystkimi przypisanymi Tobie i obserwowanymi historyjkami użytkownika, zadaniami i zgłoszeniami.", "PAGE_DESCRIPTION": "Główna strona Taiga, z Twoimi głównymi projektami i wszystkimi przypisanymi Tobie i obserwowanymi historyjkami użytkownika, zadaniami i zgłoszeniami.",
"EMPTY_WORKING_ON": "<strong>It feels empty, doesn't it?</strong> Start working with Taiga and you'll see here the stories, tasks and issues you are working on.", "EMPTY_WORKING_ON": "<strong>Trochę pusto, nieprawdaż?</strong> Zacznij pracować z Taiga a tutaj pojawią się historie, zadania i zgłoszenia nad którymi pracujesz.",
"EMPTY_WATCHING": "<strong>Follow</strong> User Stories, Tasks, Issues in your projects and be notified about its changes :)", "EMPTY_WATCHING": "<strong>Follow</strong> User Stories, Tasks, Issues in your projects and be notified about its changes :)",
"EMPTY_PROJECT_LIST": "Nie masz jeszcze żadnych projektów", "EMPTY_PROJECT_LIST": "Nie masz jeszcze żadnych projektów",
"WORKING_ON_SECTION": "Pracujesz nad", "WORKING_ON_SECTION": "Pracujesz nad",
"WATCHING_SECTION": "Obserwujesz", "WATCHING_SECTION": "Obserwujesz",
"DASHBOARD": "Projects Dashboard" "DASHBOARD": "Projects Dashboard"
}, },
"EPICS": {
"TITLE": "EPIKI",
"SECTION_NAME": "Epics",
"EPIC": "EPIK",
"PAGE_TITLE": "Epics - {{projectName}}",
"PAGE_DESCRIPTION": "The epics list of the project {{projectName}}: {{projectDescription}}",
"DASHBOARD": {
"ADD": "+DODAJ EPIK",
"UNASSIGNED": "Nieprzypisane"
},
"EMPTY": {
"TITLE": "It looks like there aren't any epics yet",
"EXPLANATION": "Epics are items at a higher level that encompass user stories.<br />Epics are at the top of the hierarchy and can be used to group user stories together.",
"HELP": "Learn more about epics"
},
"TABLE": {
"VOTES": "Głosy",
"NAME": "Nazwa",
"PROJECT": "Projekt",
"SPRINT": "Sprint",
"ASSIGNED_TO": "Assigned",
"STATUS": "Statusy",
"PROGRESS": "Progress",
"VIEW_OPTIONS": "View options"
},
"CREATE": {
"TITLE": "Nowy epik",
"PLACEHOLDER_DESCRIPTION": "Please add descriptive text to help others better understand this epic",
"TEAM_REQUIREMENT": "Wymaganie zespołu",
"CLIENT_REQUIREMENT": "Client requirement",
"BLOCKED": "Zablokowane",
"BLOCKED_NOTE_PLACEHOLDER": "Why is this epic blocked?",
"CREATE_EPIC": "Create epic"
}
},
"PROJECTS": { "PROJECTS": {
"PAGE_TITLE": "Moje projekty - Taiga", "PAGE_TITLE": "Moje projekty - Taiga",
"PAGE_DESCRIPTION": "Lista wszystkich Twoich projektów, możesz zmieniać ich kolejność lub tworzyć nowe.", "PAGE_DESCRIPTION": "Lista wszystkich Twoich projektów, możesz zmieniać ich kolejność lub tworzyć nowe.",
@ -374,13 +446,13 @@
"ATTACHMENT": { "ATTACHMENT": {
"SECTION_NAME": "załączniki", "SECTION_NAME": "załączniki",
"TITLE": "{{ plik }} załadowany dnia {{ data }}", "TITLE": "{{ plik }} załadowany dnia {{ data }}",
"LIST_VIEW_MODE": "List view mode", "LIST_VIEW_MODE": "Tryb listy",
"GALLERY_VIEW_MODE": "Gallery view mode", "GALLERY_VIEW_MODE": "Tryb galerii",
"DESCRIPTION": "Wpisz krótki opis", "DESCRIPTION": "Wpisz krótki opis",
"DEPRECATED": "(przestarzały)", "DEPRECATED": "(przestarzały)",
"DEPRECATED_FILE": "Przestarzałe?", "DEPRECATED_FILE": "Przestarzałe?",
"ADD": "Dodaj nowy załącznik. {{maxFileSizeMsg}}", "ADD": "Dodaj nowy załącznik. {{maxFileSizeMsg}}",
"DROP": "Drop attachments here!", "DROP": "Upuść załączniki tutaj",
"SHOW_DEPRECATED": "+ pokaż przestarzałe załączniki", "SHOW_DEPRECATED": "+ pokaż przestarzałe załączniki",
"HIDE_DEPRECATED": "- ukryj przestarzałe załączniki", "HIDE_DEPRECATED": "- ukryj przestarzałe załączniki",
"COUNT_DEPRECATED": "({{ counter }} przestarzałych", "COUNT_DEPRECATED": "({{ counter }} przestarzałych",
@ -402,7 +474,8 @@
"ADMIN": { "ADMIN": {
"COMMON": { "COMMON": {
"TITLE_ACTION_EDIT_VALUE": "Edytuj wartość", "TITLE_ACTION_EDIT_VALUE": "Edytuj wartość",
"TITLE_ACTION_DELETE_VALUE": "Usuń wartość" "TITLE_ACTION_DELETE_VALUE": "Usuń wartość",
"TITLE_ACTION_DELETE_TAG": "Usuń tag"
}, },
"HELP": "Potrzebujesz pomocy? Sprawdź naszą stronę wsparcia!", "HELP": "Potrzebujesz pomocy? Sprawdź naszą stronę wsparcia!",
"PROJECT_DEFAULT_VALUES": { "PROJECT_DEFAULT_VALUES": {
@ -414,7 +487,7 @@
"PAGE_TITLE": "Członkostwa - {{projectName}}", "PAGE_TITLE": "Członkostwa - {{projectName}}",
"ADD_BUTTON": "+ Nowy członek", "ADD_BUTTON": "+ Nowy członek",
"ADD_BUTTON_TITLE": "Dodaj nowego członka", "ADD_BUTTON_TITLE": "Dodaj nowego członka",
"LIMIT_USERS_WARNING_MESSAGE_FOR_ADMIN": "Unfortunately, this project has reached its limit of <strong>({{members}})</strong> allowed members.", "LIMIT_USERS_WARNING_MESSAGE_FOR_ADMIN": "Niestety ten projekt osiągnął maksymalną liczbę <strong>{{{members}}}</strong> dozwolonych użytkowników.",
"LIMIT_USERS_WARNING_MESSAGE_FOR_OWNER": "This project has reached its limit of <strong>({{members}})</strong> allowed members. If you would like to increase that limit please contact the administrator." "LIMIT_USERS_WARNING_MESSAGE_FOR_OWNER": "This project has reached its limit of <strong>({{members}})</strong> allowed members. If you would like to increase that limit please contact the administrator."
}, },
"PROJECT_EXPORT": { "PROJECT_EXPORT": {
@ -435,12 +508,14 @@
"TITLE": "Moduły", "TITLE": "Moduły",
"ENABLE": "Włącz", "ENABLE": "Włącz",
"DISABLE": "Wyłącz", "DISABLE": "Wyłącz",
"EPICS": "Epics",
"EPICS_DESCRIPTION": "Visualize and manage the most strategic part of your project",
"BACKLOG": "Dziennik", "BACKLOG": "Dziennik",
"BACKLOG_DESCRIPTION": "Zarządzaj swoimi historyjkami użytkownika aby utrzymać zorganizowany widok i priorytety zadań", "BACKLOG_DESCRIPTION": "Zarządzaj swoimi historyjkami użytkownika aby utrzymać zorganizowany widok i priorytety zadań",
"NUMBER_SPRINTS": "Expected number of sprints", "NUMBER_SPRINTS": "Expected number of sprints",
"NUMBER_SPRINTS_HELP": "0 for an undetermined number", "NUMBER_SPRINTS_HELP": "0 dla nieokreślonej liczby",
"NUMBER_US_POINTS": "Expected total of story points", "NUMBER_US_POINTS": "Expected total of story points",
"NUMBER_US_POINTS_HELP": "0 for an undetermined number", "NUMBER_US_POINTS_HELP": "0 dla nieokreślonej liczby",
"KANBAN": "Kanban", "KANBAN": "Kanban",
"KANBAN_DESCRIPTION": "Organizuj swój projekt przy użyciu metody lean.", "KANBAN_DESCRIPTION": "Organizuj swój projekt przy użyciu metody lean.",
"ISSUES": "Zgłoszenia", "ISSUES": "Zgłoszenia",
@ -464,8 +539,8 @@
"PROJECT_SLUG": "Szczegóły projektu", "PROJECT_SLUG": "Szczegóły projektu",
"TAGS": "Tagi", "TAGS": "Tagi",
"DESCRIPTION": "Opis", "DESCRIPTION": "Opis",
"RECRUITING": "Is this project looking for people?", "RECRUITING": "Czy ten pojekt szuka uczestników?",
"RECRUITING_MESSAGE": "Who are you looking for?", "RECRUITING_MESSAGE": "Kogo szukasz?",
"RECRUITING_PLACEHOLDER": "Define the profiles you are looking for", "RECRUITING_PLACEHOLDER": "Define the profiles you are looking for",
"PUBLIC_PROJECT": "Projekt publiczny", "PUBLIC_PROJECT": "Projekt publiczny",
"PRIVATE_PROJECT": "Projekt prywatny", "PRIVATE_PROJECT": "Projekt prywatny",
@ -497,6 +572,7 @@
"REGENERATE_SUBTITLE": "Zamierzasz zmienić link dostępu do danych CSV. Poprzedni link będzie niedostępny. Czy jesteś pewien?" "REGENERATE_SUBTITLE": "Zamierzasz zmienić link dostępu do danych CSV. Poprzedni link będzie niedostępny. Czy jesteś pewien?"
}, },
"CSV": { "CSV": {
"SECTION_TITLE_EPIC": "epics reports",
"SECTION_TITLE_US": "raporty historii użytkownika", "SECTION_TITLE_US": "raporty historii użytkownika",
"SECTION_TITLE_TASK": "Raporty zadań", "SECTION_TITLE_TASK": "Raporty zadań",
"SECTION_TITLE_ISSUE": "raporty zgłoszeń", "SECTION_TITLE_ISSUE": "raporty zgłoszeń",
@ -509,6 +585,8 @@
"CUSTOM_FIELDS": { "CUSTOM_FIELDS": {
"TITLE": "Własne Pola", "TITLE": "Własne Pola",
"SUBTITLE": "Zdefiniuj własne dodatkowe pola dla historyjek użytkownika, zadań i zgłoszeń.", "SUBTITLE": "Zdefiniuj własne dodatkowe pola dla historyjek użytkownika, zadań i zgłoszeń.",
"EPIC_DESCRIPTION": "Epics custom fields",
"EPIC_ADD": "Add a custom field in epics",
"US_DESCRIPTION": "Własne pola dla historyjek użytkownika", "US_DESCRIPTION": "Własne pola dla historyjek użytkownika",
"US_ADD": "Dodaj własne pole dla historyjek użytkownika", "US_ADD": "Dodaj własne pole dla historyjek użytkownika",
"TASK_DESCRIPTION": "Własne pola dla zadań", "TASK_DESCRIPTION": "Własne pola dla zadań",
@ -546,7 +624,8 @@
"PROJECT_VALUES_STATUS": { "PROJECT_VALUES_STATUS": {
"TITLE": "Status", "TITLE": "Status",
"SUBTITLE": "Zdefiniuj statusy dla historyjek użytkownika, zadań i zgłoszeń.", "SUBTITLE": "Zdefiniuj statusy dla historyjek użytkownika, zadań i zgłoszeń.",
"US_TITLE": "Statusy", "EPIC_TITLE": "Epic Statuses",
"US_TITLE": "User Story Statuses",
"TASK_TITLE": "Statusy zadań", "TASK_TITLE": "Statusy zadań",
"ISSUE_TITLE": "Statusy zgłoszeń" "ISSUE_TITLE": "Statusy zgłoszeń"
}, },
@ -556,6 +635,17 @@
"ISSUE_TITLE": "Typy zgłoszeń", "ISSUE_TITLE": "Typy zgłoszeń",
"ACTION_ADD": "Dodaj nowy {{objName}}" "ACTION_ADD": "Dodaj nowy {{objName}}"
}, },
"PROJECT_VALUES_TAGS": {
"TITLE": "Tagi",
"SUBTITLE": "View and edit the color of your tags",
"EMPTY": "Currently there are no tags",
"EMPTY_SEARCH": "It looks like nothing was found with your search criteria",
"ACTION_ADD": "Dodaj tag",
"NEW_TAG": "New tag",
"MIXING_HELP_TEXT": "Select the tags that you want to merge",
"MIXING_MERGE": "Merge Tags",
"SELECTED": "Selected"
},
"ROLES": { "ROLES": {
"PAGE_TITLE": "Role - {{projectName}}", "PAGE_TITLE": "Role - {{projectName}}",
"WARNING_NO_ROLE": "Bez przydzielenia ról w projekcie nie ma możliwości oceniania historyjek użytkownika. Umpa Lumpy nie będą wiedziały komu wolno to zrobić :)", "WARNING_NO_ROLE": "Bez przydzielenia ról w projekcie nie ma możliwości oceniania historyjek użytkownika. Umpa Lumpy nie będą wiedziały komu wolno to zrobić :)",
@ -588,6 +678,10 @@
"SECTION_NAME": "Github", "SECTION_NAME": "Github",
"PAGE_TITLE": "Github - {{projectName}}" "PAGE_TITLE": "Github - {{projectName}}"
}, },
"GOGS": {
"SECTION_NAME": "Gogs",
"PAGE_TITLE": "Gogs - {{projectName}}"
},
"WEBHOOKS": { "WEBHOOKS": {
"PAGE_TITLE": "Webhooks - {{projectName}}", "PAGE_TITLE": "Webhooks - {{projectName}}",
"SECTION_NAME": "Webhooks", "SECTION_NAME": "Webhooks",
@ -643,13 +737,14 @@
"DEFAULT_DELETE_MESSAGE": "zaproszenie do {{e-mail}}" "DEFAULT_DELETE_MESSAGE": "zaproszenie do {{e-mail}}"
}, },
"DEFAULT_VALUES": { "DEFAULT_VALUES": {
"LABEL_EPIC_STATUS": "Default value for epic status selector",
"LABEL_US_STATUS": "Default value for user story status selector",
"LABEL_POINTS": "Domyślna wartość dla selektora punktów", "LABEL_POINTS": "Domyślna wartość dla selektora punktów",
"LABEL_US": "Domyślna wartość dla selektora statusu historyjek użytkownika",
"LABEL_TASK_STATUS": "Domyśla wartość dla selektora statusu zadań", "LABEL_TASK_STATUS": "Domyśla wartość dla selektora statusu zadań",
"LABEL_PRIORITY": "Domyślna wartość dla selektora priorytetu",
"LABEL_SEVERITY": "Domyślna wartość dla selektora ważności",
"LABEL_ISSUE_TYPE": "Domyślna wartość dla selektora typu zgłoszenia", "LABEL_ISSUE_TYPE": "Domyślna wartość dla selektora typu zgłoszenia",
"LABEL_ISSUE_STATUS": "Domyślna wartość dla selektora statusu zgłoszenia" "LABEL_ISSUE_STATUS": "Domyślna wartość dla selektora statusu zgłoszenia",
"LABEL_PRIORITY": "Domyślna wartość dla selektora priorytetu",
"LABEL_SEVERITY": "Domyślna wartość dla selektora ważności"
}, },
"STATUS": { "STATUS": {
"PLACEHOLDER_WRITE_STATUS_NAME": "Wpisz nazwę nowego statusu" "PLACEHOLDER_WRITE_STATUS_NAME": "Wpisz nazwę nowego statusu"
@ -681,7 +776,8 @@
"PRIORITIES": "Priorytety", "PRIORITIES": "Priorytety",
"SEVERITIES": "Ważność", "SEVERITIES": "Ważność",
"TYPES": "Typy", "TYPES": "Typy",
"CUSTOM_FIELDS": "Niestandardowe pola" "CUSTOM_FIELDS": "Niestandardowe pola",
"TAGS": "Tagi"
}, },
"SUBMENU_PROJECT_PROFILE": { "SUBMENU_PROJECT_PROFILE": {
"TITLE": "Profil projektu" "TITLE": "Profil projektu"
@ -727,9 +823,9 @@
"REPORT": "Zgłoś naruszenie", "REPORT": "Zgłoś naruszenie",
"TABS": { "TABS": {
"ACTIVITY_TAB": "Oś czasu", "ACTIVITY_TAB": "Oś czasu",
"ACTIVITY_TAB_TITLE": "Show all the activity of this user", "ACTIVITY_TAB_TITLE": "Wyświetl całą aktywność użytkownika",
"PROJECTS_TAB": "Projekty", "PROJECTS_TAB": "Projekty",
"PROJECTS_TAB_TITLE": "List of all projects in which the user is a member", "PROJECTS_TAB_TITLE": "Lista wszystkich projektów, do których należy użytkownik",
"LIKES_TAB": "Likes", "LIKES_TAB": "Likes",
"LIKES_TAB_TITLE": "List all likes made by this user", "LIKES_TAB_TITLE": "List all likes made by this user",
"VOTES_TAB": "Głosy", "VOTES_TAB": "Głosy",
@ -743,7 +839,7 @@
"PROFILE_SIDEBAR": { "PROFILE_SIDEBAR": {
"TITLE": "Twój profil", "TITLE": "Twój profil",
"DESCRIPTION": "People can see everything you do and what you are working on. Add a nice bio to give an enhanced version of your information.", "DESCRIPTION": "People can see everything you do and what you are working on. Add a nice bio to give an enhanced version of your information.",
"ADD_INFO": "Edit bio" "ADD_INFO": "Edytuj biografię"
}, },
"PROFILE_FAVS": { "PROFILE_FAVS": {
"FILTER_INPUT_PLACEHOLDER": "Type something...", "FILTER_INPUT_PLACEHOLDER": "Type something...",
@ -751,13 +847,15 @@
"FILTER_TYPE_ALL_TITLE": "Show all", "FILTER_TYPE_ALL_TITLE": "Show all",
"FILTER_TYPE_PROJECTS": "Projekty", "FILTER_TYPE_PROJECTS": "Projekty",
"FILTER_TYPE_PROJECT_TITLES": "Show only projects", "FILTER_TYPE_PROJECT_TITLES": "Show only projects",
"FILTER_TYPE_EPICS": "Epics",
"FILTER_TYPE_EPIC_TITLES": "Show only epics",
"FILTER_TYPE_USER_STORIES": "Stories", "FILTER_TYPE_USER_STORIES": "Stories",
"FILTER_TYPE_USER_STORIES_TITLES": "Show only user stories", "FILTER_TYPE_USER_STORIES_TITLES": "Show only user stories",
"FILTER_TYPE_TASKS": "Zadania", "FILTER_TYPE_TASKS": "Zadania",
"FILTER_TYPE_TASK_TITLES": "Show only tasks", "FILTER_TYPE_TASK_TITLES": "Show only tasks",
"FILTER_TYPE_ISSUES": "Zgłoszenia", "FILTER_TYPE_ISSUES": "Zgłoszenia",
"FILTER_TYPE_ISSUES_TITLE": "Show only issues", "FILTER_TYPE_ISSUES_TITLE": "Show only issues",
"EMPTY_TITLE": "It looks like there's nothing to show here." "EMPTY_TITLE": "Wygląda na to, że nie ma niczego do wyświetlenia tutaj."
} }
}, },
"PROJECT": { "PROJECT": {
@ -766,14 +864,14 @@
"SECTION_PROJECTS": "Projekty", "SECTION_PROJECTS": "Projekty",
"HELP": "Ustal kolejność Twoich projektów tak, aby na górze znalazły się te najważniejsze. <br/> Pierwsze 10 projektów pojawi się w liście projektów na górnym pasku nawigacji.", "HELP": "Ustal kolejność Twoich projektów tak, aby na górze znalazły się te najważniejsze. <br/> Pierwsze 10 projektów pojawi się w liście projektów na górnym pasku nawigacji.",
"PRIVATE": "Projekt prywatny", "PRIVATE": "Projekt prywatny",
"LOOKING_FOR_PEOPLE": "This project is looking for people", "LOOKING_FOR_PEOPLE": "Ten projekt szuka uczestników",
"FANS_COUNTER_TITLE": "{total, plural, one{one fan} other{# fans}}", "FANS_COUNTER_TITLE": "{total, plural, one{one fan} other{# fans}}",
"WATCHERS_COUNTER_TITLE": "{total, plural, one{one watcher} other{# watchers}}", "WATCHERS_COUNTER_TITLE": "{total, plural, one{one watcher} other{# watchers}}",
"MEMBERS_COUNTER_TITLE": "{total, plural, one{one member} other{# members}}", "MEMBERS_COUNTER_TITLE": "{total, plural, one{one member} other{# members}}",
"BLOCKED_PROJECT": { "BLOCKED_PROJECT": {
"BLOCKED": "Blocked project", "BLOCKED": "Projekt zablokowany",
"THIS_PROJECT_IS_BLOCKED": "This project is temporarily blocked", "THIS_PROJECT_IS_BLOCKED": "Ten projekt jest tymczasowo zablokowany",
"TO_UNBLOCK_CONTACT_THE_ADMIN_STAFF": "In order to unblock your projects, contact the administrator." "TO_UNBLOCK_CONTACT_THE_ADMIN_STAFF": "Aby odblokować swój projekt, skontaktuj się z administacją"
}, },
"STATS": { "STATS": {
"PROJECT": "projekt<br/> punkty", "PROJECT": "projekt<br/> punkty",
@ -890,8 +988,8 @@
"SECTION_NAME": "Usuń konto z Taiga", "SECTION_NAME": "Usuń konto z Taiga",
"CONFIRM": "Czy na pewno chcesz usunąć swoje konto z Taiga?", "CONFIRM": "Czy na pewno chcesz usunąć swoje konto z Taiga?",
"NEWSLETTER_LABEL_TEXT": "Nie chcę więcej otrzymywać waszego newslettera", "NEWSLETTER_LABEL_TEXT": "Nie chcę więcej otrzymywać waszego newslettera",
"CANCEL": "Back to settings", "CANCEL": "Powrót do ustawień",
"ACCEPT": "Delete account", "ACCEPT": "Usuń konto",
"BLOCK_PROJECT": "Note that all the projects you own projects will be <strong>blocked</strong> after you delete your account. If you do want a project blocked, transfer ownership to another member of each project prior to deleting your account.", "BLOCK_PROJECT": "Note that all the projects you own projects will be <strong>blocked</strong> after you delete your account. If you do want a project blocked, transfer ownership to another member of each project prior to deleting your account.",
"SUBTITLE": "Sorry to see you go. We'll be here if you should ever consider us again! :(" "SUBTITLE": "Sorry to see you go. We'll be here if you should ever consider us again! :("
}, },
@ -950,8 +1048,8 @@
"CREATE_MEMBER": { "CREATE_MEMBER": {
"PLACEHOLDER_INVITATION_TEXT": "(Opcjonalne) Dodaj spersonalizowany tekst do zaproszenia. Napisz coś słodziachnego do nowego członka zespołu :)", "PLACEHOLDER_INVITATION_TEXT": "(Opcjonalne) Dodaj spersonalizowany tekst do zaproszenia. Napisz coś słodziachnego do nowego członka zespołu :)",
"PLACEHOLDER_TYPE_EMAIL": "Wpisz Email", "PLACEHOLDER_TYPE_EMAIL": "Wpisz Email",
"LIMIT_USERS_WARNING_MESSAGE_FOR_OWNER": "Unfortunately, this project can't have more than <strong>{{maxMembers}}</strong> members.<br> If you would like to increase the current limit, please contact the administrator.", "LIMIT_USERS_WARNING_MESSAGE_FOR_OWNER": "You are about to reach the maximum number of members allowed for this project, <strong>{{maxMembers}}</strong> members. If you would like to increase the current limit, please contact the administrator.",
"LIMIT_USERS_WARNING_MESSAGE": "Unfortunately, this project can't have more than <strong>{{maxMembers}}</strong> members." "LIMIT_USERS_WARNING_MESSAGE": "You are about to reach the maximum number of members allowed for this project, <strong>{{maxMembers}}</strong> members."
}, },
"LEAVE_PROJECT_WARNING": { "LEAVE_PROJECT_WARNING": {
"TITLE": "Unfortunately, this project can't be left without an owner", "TITLE": "Unfortunately, this project can't be left without an owner",
@ -970,10 +1068,30 @@
"BUTTON": "Ask this project member to become the new project owner" "BUTTON": "Ask this project member to become the new project owner"
} }
}, },
"EPIC": {
"PAGE_TITLE": "{{epicSubject}} - Epic {{epicRef}} - {{projectName}}",
"PAGE_DESCRIPTION": "Status: {{epicStatus }}. Description: {{epicDescription}}",
"SECTION_NAME": "Epic",
"TITLE_LIGHTBOX_UNLINK_RELATED_USERSTORY": "Unlink related userstory",
"MSG_LIGHTBOX_UNLINK_RELATED_USERSTORY": "It will delete the link to the related userstory '{{subject}}'",
"ERROR_UNLINK_RELATED_USERSTORY": "We have not been able to unlink: {{errorMessage}}",
"CREATE_RELATED_USERSTORIES": "Create a relationship with",
"NEW_USERSTORY": "Nowa historyjka użytkownika",
"EXISTING_USERSTORY": "Existing user story",
"CHOOSE_PROJECT_FOR_CREATION": "What's the project?",
"SUBJECT": "Temat",
"SUBJECT_BULK_MODE": "Subject (bulk insert)",
"CHOOSE_PROJECT_FROM": "What's the project?",
"CHOOSE_USERSTORY": "What's the user story?",
"NO_USERSTORIES": "This project has no User Stories yet. Please select another project.",
"FILTER_USERSTORIES": "Filter user stories",
"LIGHTBOX_TITLE_BLOKING_EPIC": "Blocking epic",
"ACTION_DELETE": "Delete epic"
},
"US": { "US": {
"PAGE_TITLE": "{{userStorySubject}} - Historyjka użytkownika {{userStoryRef}} - {{projectName}}", "PAGE_TITLE": "{{userStorySubject}} - Historyjka użytkownika {{userStoryRef}} - {{projectName}}",
"PAGE_DESCRIPTION": "Status: {{userStoryStatus }}. Zakończono {{userStoryProgressPercentage}}% ({{userStoryClosedTasks}} z {{userStoryTotalTasks}} zadań). Punktów: {{userStoryPoints}}. Opis: {{userStoryDescription}}", "PAGE_DESCRIPTION": "Status: {{userStoryStatus }}. Zakończono {{userStoryProgressPercentage}}% ({{userStoryClosedTasks}} z {{userStoryTotalTasks}} zadań). Punktów: {{userStoryPoints}}. Opis: {{userStoryDescription}}",
"SECTION_NAME": "Szczegóły historyjki użytkownika", "SECTION_NAME": "Historyjka użytkownika",
"LINK_TASKBOARD": "Tablica zadań", "LINK_TASKBOARD": "Tablica zadań",
"TITLE_LINK_TASKBOARD": "Idź do listy zadań", "TITLE_LINK_TASKBOARD": "Idź do listy zadań",
"TOTAL_POINTS": "total points", "TOTAL_POINTS": "total points",
@ -984,14 +1102,23 @@
"EXTERNAL_REFERENCE": "Ta historyjka została utworzona z", "EXTERNAL_REFERENCE": "Ta historyjka została utworzona z",
"GO_TO_EXTERNAL_REFERENCE": "Idź do źródła", "GO_TO_EXTERNAL_REFERENCE": "Idź do źródła",
"BLOCKED": "Ta historia użytkownika jest zablokowana", "BLOCKED": "Ta historia użytkownika jest zablokowana",
"PREVIOUS": "poprzednia historia użytkownika",
"NEXT": "następna historia użytkownika",
"TITLE_DELETE_ACTION": "Usuń historyjkę użytkownika", "TITLE_DELETE_ACTION": "Usuń historyjkę użytkownika",
"LIGHTBOX_TITLE_BLOKING_US": "Blokuje nas", "LIGHTBOX_TITLE_BLOKING_US": "Blokuje nas",
"TASK_COMPLETED": "{{totalClosedTasks}}/{{totalTasks}} zadanie zakończone", "TASK_COMPLETED": "{{totalClosedTasks}}/{{totalTasks}} zadanie zakończone",
"ASSIGN": "Przypisz historyjkę użytkownika", "ASSIGN": "Przypisz historyjkę użytkownika",
"NOT_ESTIMATED": "Nie oszacowane", "NOT_ESTIMATED": "Nie oszacowane",
"TOTAL_US_POINTS": "Łącznie punktów", "TOTAL_US_POINTS": "Łącznie punktów",
"TRIBE": {
"PUBLISH": "Publish as Gig in Taiga Tribe",
"PUBLISH_INFO": "More info",
"PUBLISH_TITLE": "More info on publishing in Taiga Tribe",
"PUBLISHED_AS_GIG": "Story published as Gig in Taiga Tribe",
"EDIT_LINK": "Edit link",
"CLOSE": "Close",
"SYNCHRONIZE_LINK": "synchronize with Taiga Tribe",
"PUBLISH_MORE_INFO_TITLE": "Do you need somebody for this task?",
"PUBLISH_MORE_INFO_TEXT": "<p>If you need help with a particular piece of work you can easily create gigs on<a href='taigatribe.com' title='Taiga Tribe'> Taiga Tribe </a> and receive help from all over the world. You will be able to control and manage the gig enjoying a great community eager to contribute.</p><p><a href='taigatribe.com' title='Taiga Tribe'> TaigaTribe </a> was born as a Taiga sibling. Both platforms can live separately but we believe that there is much power in using them combined so we are making sure the integration works like a charm.</p>"
},
"FIELDS": { "FIELDS": {
"TEAM_REQUIREMENT": "Wymaganie zespołu", "TEAM_REQUIREMENT": "Wymaganie zespołu",
"CLIENT_REQUIREMENT": "Wymaganie klienta", "CLIENT_REQUIREMENT": "Wymaganie klienta",
@ -999,28 +1126,47 @@
} }
}, },
"COMMENTS": { "COMMENTS": {
"DELETED_INFO": "Komentarz usunięty przez {{user}} w dniu {{date}}", "DELETED_INFO": "Komentarz usunięty przez {{user}}",
"TITLE": "Komentarze", "TITLE": "Komentarze",
"COMMENTS_COUNT": "{{comments}} Comments",
"ORDER": "Order",
"OLDER_FIRST": "Older first",
"RECENT_FIRST": "Ostatnie najpierw",
"COMMENT": "Komentarz", "COMMENT": "Komentarz",
"EDIT_COMMENT": "Edytuj komentarz",
"EDITED_COMMENT": "Edytowano",
"SHOW_HISTORY": "View historic",
"TYPE_NEW_COMMENT": "Tutaj wpisz nowy komentarz", "TYPE_NEW_COMMENT": "Tutaj wpisz nowy komentarz",
"SHOW_DELETED": "Pokaż usunięty komentarz", "SHOW_DELETED": "Pokaż usunięty komentarz",
"HIDE_DELETED": "Ukryj skasowane komentarze", "HIDE_DELETED": "Ukryj skasowane komentarze",
"DELETE": "Delete comment", "DELETE": "Delete comment",
"RESTORE": "Przywróć komentarz" "RESTORE": "Przywróć komentarz",
"HISTORY": {
"TITLE": "Aktywność"
}
}, },
"ACTIVITY": { "ACTIVITY": {
"SHOW_ACTIVITY": "Pokaż aktywność", "SHOW_ACTIVITY": "Pokaż aktywność",
"DATETIME": "DD MMM YYYY HH:mm", "DATETIME": "DD MMM YYYY HH:mm",
"SHOW_MORE": "+ Pokaż poprzednie wpisy ({{showMore}} więcej)", "SHOW_MORE": "+ Pokaż poprzednie wpisy ({{showMore}} więcej)",
"TITLE": "Aktywność", "TITLE": "Aktywność",
"ACTIVITIES_COUNT": "{{activities}} Activities",
"REMOVED": "usunięty", "REMOVED": "usunięty",
"ADDED": "dodany", "ADDED": "dodany",
"US_POINTS": "Punkty HU ({{name}})", "TAGS_ADDED": "dodano klucz",
"TAGS_REMOVED": "usunięto tag:",
"US_POINTS": "{{role}} points",
"NEW_ATTACHMENT": "nowy załącznik", "NEW_ATTACHMENT": "nowy załącznik",
"DELETED_ATTACHMENT": "Usunięty załącznik", "DELETED_ATTACHMENT": "deleted attachment:",
"UPDATED_ATTACHMENT": "Zaktualizowany załącznik {{filename}}", "UPDATED_ATTACHMENT": "updated attachment ({{filename}}):",
"DELETED_CUSTOM_ATTRIBUTE": "Usunięty niestandardowy atrybut", "CREATED_CUSTOM_ATTRIBUTE": "created custom attribute",
"UPDATED_CUSTOM_ATTRIBUTE": "updated custom attribute",
"SIZE_CHANGE": "Dokonano {size, plural, one{one change} other{# changes}}", "SIZE_CHANGE": "Dokonano {size, plural, one{one change} other{# changes}}",
"BECAME_DEPRECATED": "became deprecated",
"BECAME_UNDEPRECATED": "became undeprecated",
"TEAM_REQUIREMENT": "Wymaganie zespołu",
"CLIENT_REQUIREMENT": "Wymaganie klienta",
"BLOCKED": "Zablokowane",
"VALUES": { "VALUES": {
"YES": "tak", "YES": "tak",
"NO": "nie", "NO": "nie",
@ -1052,12 +1198,14 @@
"TAGS": "tagi", "TAGS": "tagi",
"ATTACHMENTS": "załączniki", "ATTACHMENTS": "załączniki",
"IS_DEPRECATED": "jest przedawniony", "IS_DEPRECATED": "jest przedawniony",
"IS_NOT_DEPRECATED": "is not deprecated",
"ORDER": "kolejność", "ORDER": "kolejność",
"BACKLOG_ORDER": "kolejność backlogu", "BACKLOG_ORDER": "kolejność backlogu",
"SPRINT_ORDER": "kolejność sprintów", "SPRINT_ORDER": "kolejność sprintów",
"KANBAN_ORDER": "kolejność kanban", "KANBAN_ORDER": "kolejność kanban",
"TASKBOARD_ORDER": "kolejność tablicy zadań", "TASKBOARD_ORDER": "kolejność tablicy zadań",
"US_ORDER": "Kolejność HU" "US_ORDER": "Kolejność HU",
"COLOR": "kolor"
} }
}, },
"BACKLOG": { "BACKLOG": {
@ -1069,7 +1217,7 @@
"CUSTOMIZE_GRAPH_ADMIN": "Admin", "CUSTOMIZE_GRAPH_ADMIN": "Admin",
"CUSTOMIZE_GRAPH_TITLE": "Set up the points and sprints through the Admin", "CUSTOMIZE_GRAPH_TITLE": "Set up the points and sprints through the Admin",
"MOVE_US_TO_CURRENT_SPRINT": "Przejdź do bieżącego sprintu", "MOVE_US_TO_CURRENT_SPRINT": "Przejdź do bieżącego sprintu",
"MOVE_US_TO_LATEST_SPRINT": "Move to latest Sprint", "MOVE_US_TO_LATEST_SPRINT": "Przejdź do ostatniego sprintu",
"SHOW_FILTERS": "Pokaż filtry", "SHOW_FILTERS": "Pokaż filtry",
"SHOW_TAGS": "Pokaż tagi", "SHOW_TAGS": "Pokaż tagi",
"EMPTY": "The backlog is empty!", "EMPTY": "The backlog is empty!",
@ -1109,7 +1257,8 @@
"CLOSED_TASKS": "zamkniętych<br />zadań", "CLOSED_TASKS": "zamkniętych<br />zadań",
"IOCAINE_DOSES": "dawek<br />Iokainy", "IOCAINE_DOSES": "dawek<br />Iokainy",
"SHOW_STATISTICS_TITLE": "Pokaż statystyki", "SHOW_STATISTICS_TITLE": "Pokaż statystyki",
"TOGGLE_BAKLOG_GRAPH": "Pokaż/Ukryj wykres spalania" "TOGGLE_BAKLOG_GRAPH": "Pokaż/Ukryj wykres spalania",
"POINTS_PER_ROLE": "Points per role"
}, },
"SUMMARY": { "SUMMARY": {
"PROJECT_POINTS": "punktów w<br />projekcie", "PROJECT_POINTS": "punktów w<br />projekcie",
@ -1122,9 +1271,7 @@
"TITLE": "Filtry", "TITLE": "Filtry",
"REMOVE": "Usuń filtry", "REMOVE": "Usuń filtry",
"HIDE": "Ukryj filtry", "HIDE": "Ukryj filtry",
"SHOW": "Pokaż filtry", "SHOW": "Pokaż filtry"
"FILTER_CATEGORY_STATUS": "Status",
"FILTER_CATEGORY_TAGS": "Tagi"
}, },
"SPRINTS": { "SPRINTS": {
"TITLE": "SPRINTY", "TITLE": "SPRINTY",
@ -1179,7 +1326,7 @@
"TASK": { "TASK": {
"PAGE_TITLE": "{{taskSubject}} - Zadanie {{taskRef}} - {{projectName}}", "PAGE_TITLE": "{{taskSubject}} - Zadanie {{taskRef}} - {{projectName}}",
"PAGE_DESCRIPTION": "Status: {{taskStatus }}. Opis: {{taskDescription}}", "PAGE_DESCRIPTION": "Status: {{taskStatus }}. Opis: {{taskDescription}}",
"SECTION_NAME": "Szczegóły zadania", "SECTION_NAME": "Zadania",
"LINK_TASKBOARD": "Tablica zadań", "LINK_TASKBOARD": "Tablica zadań",
"TITLE_LINK_TASKBOARD": "Idź do listy zadań", "TITLE_LINK_TASKBOARD": "Idź do listy zadań",
"PLACEHOLDER_SUBJECT": "Wpisz temat zadania", "PLACEHOLDER_SUBJECT": "Wpisz temat zadania",
@ -1189,8 +1336,6 @@
"ORIGIN_US": "Źródło tego zadania to", "ORIGIN_US": "Źródło tego zadania to",
"TITLE_LINK_GO_ORIGIN": "Idź do historyjki użytkownika", "TITLE_LINK_GO_ORIGIN": "Idź do historyjki użytkownika",
"BLOCKED": "To zadanie jest zablokowane", "BLOCKED": "To zadanie jest zablokowane",
"PREVIOUS": "poprzednie zadanie",
"NEXT": "następne zadanie",
"TITLE_DELETE_ACTION": "Usuń zadanie", "TITLE_DELETE_ACTION": "Usuń zadanie",
"LIGHTBOX_TITLE_BLOKING_TASK": "Blokowanie zadania", "LIGHTBOX_TITLE_BLOKING_TASK": "Blokowanie zadania",
"FIELDS": { "FIELDS": {
@ -1228,16 +1373,13 @@
"PAGE_TITLE": "Zgłoszenia - {{projectName}}", "PAGE_TITLE": "Zgłoszenia - {{projectName}}",
"PAGE_DESCRIPTION": "Lista zgłoszeń w projekcie {{projectName}}: {{projectDescription}}", "PAGE_DESCRIPTION": "Lista zgłoszeń w projekcie {{projectName}}: {{projectDescription}}",
"LIST_SECTION_NAME": "Zgłoszenia", "LIST_SECTION_NAME": "Zgłoszenia",
"SECTION_NAME": "Szczegóły zgłoszenia", "SECTION_NAME": "Zgłoszenie",
"ACTION_NEW_ISSUE": "+ NOWE ZGŁOSZENIE", "ACTION_NEW_ISSUE": "+ NOWE ZGŁOSZENIE",
"ACTION_PROMOTE_TO_US": "Awansuj na historyjkę użytkownika", "ACTION_PROMOTE_TO_US": "Awansuj na historyjkę użytkownika",
"PLACEHOLDER_FILTER_NAME": "Wpisz nazwę filtru i kliknij enter",
"PROMOTED": "To zgłoszenie zostało wypromowane na HU:", "PROMOTED": "To zgłoszenie zostało wypromowane na HU:",
"EXTERNAL_REFERENCE": "Źródło zgłoszenia", "EXTERNAL_REFERENCE": "Źródło zgłoszenia",
"GO_TO_EXTERNAL_REFERENCE": "Idź do źródła", "GO_TO_EXTERNAL_REFERENCE": "Idź do źródła",
"BLOCKED": "To zgłoszenie jest zablokowane", "BLOCKED": "To zgłoszenie jest zablokowane",
"TITLE_PREVIOUS_ISSUE": "poprzednie zgłoszenie",
"TITLE_NEXT_ISSUE": "następne zgłoszenie",
"ACTION_DELETE": "Usuń zgłoszenie", "ACTION_DELETE": "Usuń zgłoszenie",
"LIGHTBOX_TITLE_BLOKING_ISSUE": "Blokowanie zgłoszenia", "LIGHTBOX_TITLE_BLOKING_ISSUE": "Blokowanie zgłoszenia",
"FIELDS": { "FIELDS": {
@ -1249,28 +1391,6 @@
"TITLE": "Awansuj to zgłoszenie na historyjkę użytkownika", "TITLE": "Awansuj to zgłoszenie na historyjkę użytkownika",
"MESSAGE": "Jesteś pewny, że chcesz wypromować to zgłoszenie na historyjkę użytkownika?" "MESSAGE": "Jesteś pewny, że chcesz wypromować to zgłoszenie na historyjkę użytkownika?"
}, },
"FILTERS": {
"TITLE": "Filtry",
"INPUT_SEARCH_PLACEHOLDER": "Temat lub referencja",
"TITLE_ACTION_SEARCH": "Szukaj",
"ACTION_SAVE_CUSTOM_FILTER": "zapisz jako filtr niestandardowy",
"BREADCRUMB": "Filtry",
"TITLE_BREADCRUMB": "Filtry",
"CATEGORIES": {
"TYPE": "Typy",
"STATUS": "Statusy",
"SEVERITY": "Ważność",
"PRIORITIES": "Priorytety",
"TAGS": "Tagi",
"ASSIGNED_TO": "Przypisane do",
"CREATED_BY": "Stworzona przez",
"CUSTOM_FILTERS": "Filtry niestandardowe"
},
"CONFIRM_DELETE": {
"TITLE": "Usuń filtr niestandardowy",
"MESSAGE": "filtr niestandardowy '{{customFilterName}}'"
}
},
"TABLE": { "TABLE": {
"COLUMNS": { "COLUMNS": {
"TYPE": "Typ", "TYPE": "Typ",
@ -1316,6 +1436,7 @@
"SEARCH": { "SEARCH": {
"PAGE_TITLE": "Szukaj - {{projectName}}", "PAGE_TITLE": "Szukaj - {{projectName}}",
"PAGE_DESCRIPTION": "Możesz przeszukiwać wszystko, historyjki użytkownika, zgłoszenia, zadania oraz strony Wiki w projekcie {{projectName}}: {{projectDescription}}", "PAGE_DESCRIPTION": "Możesz przeszukiwać wszystko, historyjki użytkownika, zgłoszenia, zadania oraz strony Wiki w projekcie {{projectName}}: {{projectDescription}}",
"FILTER_EPICS": "Epics",
"FILTER_USER_STORIES": "Historyjki użytkownika", "FILTER_USER_STORIES": "Historyjki użytkownika",
"FILTER_ISSUES": "Zgłoszenia", "FILTER_ISSUES": "Zgłoszenia",
"FILTER_TASKS": "Zadania", "FILTER_TASKS": "Zadania",
@ -1417,13 +1538,24 @@
"DELETE_LIGHTBOX_TITLE": "Usuń tą stronę Wiki", "DELETE_LIGHTBOX_TITLE": "Usuń tą stronę Wiki",
"DELETE_LINK_TITLE": "Delete Wiki link", "DELETE_LINK_TITLE": "Delete Wiki link",
"NAVIGATION": { "NAVIGATION": {
"SECTION_NAME": "Linki", "HOME": "Main Page",
"ACTION_ADD_LINK": "Dodaj link" "SECTION_NAME": "BOOKMARKS",
"ACTION_ADD_LINK": "Add bookmark",
"ALL_PAGES": "All wiki pages"
}, },
"SUMMARY": { "SUMMARY": {
"TIMES_EDITED": "razy <br />edytowano", "TIMES_EDITED": "razy <br />edytowano",
"LAST_EDIT": "ostatnia <br />edycja", "LAST_EDIT": "ostatnia <br />edycja",
"LAST_MODIFICATION": "ostatnia modyfikacja" "LAST_MODIFICATION": "ostatnia modyfikacja"
},
"SECTION_PAGES_LIST": "All pages",
"PAGES_LIST_COLUMNS": {
"TITLE": "Title",
"EDITIONS": "Editions",
"CREATED": "Utworzone",
"MODIFIED": "Modified",
"CREATOR": "Creator",
"LAST_MODIFIER": "Last modifier"
} }
}, },
"HINTS": { "HINTS": {
@ -1447,6 +1579,8 @@
"TASK_CREATED_WITH_US": "Użytkownik {{username}} utworzył nowe zadanie {{obj_name}} w projekcie {{project_name}} należące do HU {{us_name}}", "TASK_CREATED_WITH_US": "Użytkownik {{username}} utworzył nowe zadanie {{obj_name}} w projekcie {{project_name}} należące do HU {{us_name}}",
"WIKI_CREATED": "Użytkownik {{username}} utworzył nową stronę Wiki {{obj_name}} w projekcie {{project_name}}", "WIKI_CREATED": "Użytkownik {{username}} utworzył nową stronę Wiki {{obj_name}} w projekcie {{project_name}}",
"MILESTONE_CREATED": "Użytkownik {{username}} utworzył nowy sprint {{obj_name}} w projekcie {{project_name}}", "MILESTONE_CREATED": "Użytkownik {{username}} utworzył nowy sprint {{obj_name}} w projekcie {{project_name}}",
"EPIC_CREATED": "{{username}} has created a new epic {{obj_name}} in {{project_name}}",
"EPIC_RELATED_USERSTORY_CREATED": "{{username}} has related the userstory {{related_us_name}} to the epic {{epic_name}} in {{project_name}}",
"NEW_PROJECT": "Użytkownik {{username}} utworzył projekt {{project_name}}", "NEW_PROJECT": "Użytkownik {{username}} utworzył projekt {{project_name}}",
"MILESTONE_UPDATED": "Użytkownik {{username}} zaktualizował sprint {{obj_name}}", "MILESTONE_UPDATED": "Użytkownik {{username}} zaktualizował sprint {{obj_name}}",
"US_UPDATED": "Użytkownik {{username}} zaktualizował atrybut {{field_name}} historyjki użytkownika {{obj_name}}", "US_UPDATED": "Użytkownik {{username}} zaktualizował atrybut {{field_name}} historyjki użytkownika {{obj_name}}",
@ -1459,9 +1593,13 @@
"TASK_UPDATED_WITH_US": "Użytkownik {{username}} zaktualizował atrybut {{field_name}} zadania {{obj_name}} należącego do HU {{us_name}}", "TASK_UPDATED_WITH_US": "Użytkownik {{username}} zaktualizował atrybut {{field_name}} zadania {{obj_name}} należącego do HU {{us_name}}",
"TASK_UPDATED_WITH_US_NEW_VALUE": "Użytkownik {{username}} zaktualizował atrybut {{field_name}} zadania {{obj_name}} należącego do HU {{us_name}} na {{new_value}}", "TASK_UPDATED_WITH_US_NEW_VALUE": "Użytkownik {{username}} zaktualizował atrybut {{field_name}} zadania {{obj_name}} należącego do HU {{us_name}} na {{new_value}}",
"WIKI_UPDATED": "Użytkownik {{username}} zaktualizował stronę Wiki {{obj_name}}", "WIKI_UPDATED": "Użytkownik {{username}} zaktualizował stronę Wiki {{obj_name}}",
"EPIC_UPDATED": "{{username}} has updated the attribute \"{{field_name}}\" of the epic {{obj_name}}",
"EPIC_UPDATED_WITH_NEW_VALUE": "{{username}} has updated the attribute \"{{field_name}}\" of the epic {{obj_name}} to {{new_value}}",
"EPIC_UPDATED_WITH_NEW_COLOR": "{{username}} has updated the \"{{field_name}}\" of the epic {{obj_name}} to <span class=\"new-color\" style=\"background: {{new_value}}\"></span>",
"NEW_COMMENT_US": "Użytkownik {{username}} skomentował historyjkę użytkownika {{obj_name}}", "NEW_COMMENT_US": "Użytkownik {{username}} skomentował historyjkę użytkownika {{obj_name}}",
"NEW_COMMENT_ISSUE": "Użytkownik {{username}} skomentował zgłoszenie {{obj_name}}", "NEW_COMMENT_ISSUE": "Użytkownik {{username}} skomentował zgłoszenie {{obj_name}}",
"NEW_COMMENT_TASK": "Użytkownik {{username}} skomentował zadanie {{obj_name}}", "NEW_COMMENT_TASK": "Użytkownik {{username}} skomentował zadanie {{obj_name}}",
"NEW_COMMENT_EPIC": "{{username}} has commented in the epic {{obj_name}}",
"NEW_MEMBER": "Projekt {{project_name}} ma nowego członka", "NEW_MEMBER": "Projekt {{project_name}} ma nowego członka",
"US_ADDED_MILESTONE": "Użytkownik{{username}} dodał HU {{obj_name}} do {{sprint_name}}", "US_ADDED_MILESTONE": "Użytkownik{{username}} dodał HU {{obj_name}} do {{sprint_name}}",
"US_MOVED": "{{username}} przeniósł historyjkę użytkownika {{obj_name}}", "US_MOVED": "{{username}} przeniósł historyjkę użytkownika {{obj_name}}",
@ -1553,7 +1691,7 @@
"MOST_LIKED": "Most liked", "MOST_LIKED": "Most liked",
"MOST_LIKED_EMPTY": "There are no LIKED projects yet", "MOST_LIKED_EMPTY": "There are no LIKED projects yet",
"VIEW_MORE": "View more", "VIEW_MORE": "View more",
"RECRUITING": "This project is looking for people", "RECRUITING": "Ten projekt szuka ludzi",
"FEATURED": "Featured Projects", "FEATURED": "Featured Projects",
"EMPTY": "There are no projects to show with this search criteria.<br> Try again!", "EMPTY": "There are no projects to show with this search criteria.<br> Try again!",
"FILTERS": { "FILTERS": {

View File

@ -35,6 +35,8 @@
"ONE_ITEM_LINE": "Um item por linha...", "ONE_ITEM_LINE": "Um item por linha...",
"NEW_BULK": "Nova inserção em lote", "NEW_BULK": "Nova inserção em lote",
"RELATED_TASKS": "Tarefas relacionadas", "RELATED_TASKS": "Tarefas relacionadas",
"PREVIOUS": "Anterior",
"NEXT": "Próximo",
"LOGOUT": "Sair", "LOGOUT": "Sair",
"EXTERNAL_USER": "um usuário externo", "EXTERNAL_USER": "um usuário externo",
"GENERIC_ERROR": "Um Oompa Loompas disse {{error}}.", "GENERIC_ERROR": "Um Oompa Loompas disse {{error}}.",
@ -43,8 +45,13 @@
"TEAM_REQUIREMENT": "Requisito de time é um requisito que deve existir no projeto, mas que não deve ter nenhum custo para o cliente.", "TEAM_REQUIREMENT": "Requisito de time é um requisito que deve existir no projeto, mas que não deve ter nenhum custo para o cliente.",
"OWNER": "Dono do Projeto", "OWNER": "Dono do Projeto",
"CAPSLOCK_WARNING": "Seja cuidadoso! Você está escrevendo em letras maiúsculas e esse campo é case sensitive, ou seja, trata com distinção as letras maiúsculas das minúsculas.", "CAPSLOCK_WARNING": "Seja cuidadoso! Você está escrevendo em letras maiúsculas e esse campo é case sensitive, ou seja, trata com distinção as letras maiúsculas das minúsculas.",
"CONFIRM_CLOSE_EDIT_MODE_TITLE": "Are you sure you want to close the edit mode?", "CONFIRM_CLOSE_EDIT_MODE_TITLE": "Você tem certeza que quer fechar o modo de edição?",
"CONFIRM_CLOSE_EDIT_MODE_MESSAGE": "Remember that if you close the edit mode without saving all the changes will be lost", "CONFIRM_CLOSE_EDIT_MODE_MESSAGE": "Lembre-se que se você fechar o modo de edição sem salvar, todas as mudanças serão perdidas",
"RELATED_USERSTORIES": "Related user stories",
"CARD": {
"ASSIGN_TO": "Assign To",
"EDIT": "Edit card"
},
"FORM_ERRORS": { "FORM_ERRORS": {
"DEFAULT_MESSAGE": "Este valor parece ser inválido.", "DEFAULT_MESSAGE": "Este valor parece ser inválido.",
"TYPE_EMAIL": "Este valor deve ser um e-mail válido.", "TYPE_EMAIL": "Este valor deve ser um e-mail válido.",
@ -69,7 +76,7 @@
"MAX_CHECK": "Você deve selecionar %s escolhas ou menos.", "MAX_CHECK": "Você deve selecionar %s escolhas ou menos.",
"RANGE_CHECK": "Você deve selecionar entre %s e %s escolhas.", "RANGE_CHECK": "Você deve selecionar entre %s e %s escolhas.",
"EQUAL_TO": "Esse valor deveria ser o mesmo.", "EQUAL_TO": "Esse valor deveria ser o mesmo.",
"LINEWIDTH": "One or more lines is perhaps too long. Try to keep under %s characters.", "LINEWIDTH": "Talvez uma ou mais linhas estejam muito grandes. Tente usar menos de %s caracteres.",
"PIKADAY": "Formato de data inválido, por favor, use DD MMM YYYY (exemplo: 23 Mar 1984)" "PIKADAY": "Formato de data inválido, por favor, use DD MMM YYYY (exemplo: 23 Mar 1984)"
}, },
"PICKERDATE": { "PICKERDATE": {
@ -115,8 +122,9 @@
"USER_STORY": "História de usuário", "USER_STORY": "História de usuário",
"TASK": "Tarefa", "TASK": "Tarefa",
"ISSUE": "Problema", "ISSUE": "Problema",
"EPIC": "Épico",
"TAGS": { "TAGS": {
"PLACEHOLDER": "Adicionar tags...", "PLACEHOLDER": "Enter tag",
"DELETE": "Apagar tag", "DELETE": "Apagar tag",
"ADD": "Adicionar tag" "ADD": "Adicionar tag"
}, },
@ -193,12 +201,29 @@
"CONFIRM_DELETE": "Remeber that all values in this custom field will be deleted.\n Are you sure you want to continue?" "CONFIRM_DELETE": "Remeber that all values in this custom field will be deleted.\n Are you sure you want to continue?"
}, },
"FILTERS": { "FILTERS": {
"TITLE": "filtros", "TITLE": "Filtros",
"INPUT_PLACEHOLDER": "Assunto ou referência", "INPUT_PLACEHOLDER": "Assunto ou referência",
"TITLE_ACTION_FILTER_BUTTON": "procurar", "TITLE_ACTION_FILTER_BUTTON": "procurar",
"BREADCRUMB_TITLE": "voltar para categorias", "INPUT_SEARCH_PLACEHOLDER": "Assunto ou ref",
"BREADCRUMB_FILTERS": "Filtros", "TITLE_ACTION_SEARCH": "Procurar",
"BREADCRUMB_STATUS": "status" "ACTION_SAVE_CUSTOM_FILTER": "salve como filtro personalizado",
"PLACEHOLDER_FILTER_NAME": "Digite o nome do filtro e pressione Enter",
"APPLIED_FILTERS_NUM": "filters applied",
"CATEGORIES": {
"TYPE": "Tipo",
"STATUS": "Status",
"SEVERITY": "Gravidade",
"PRIORITIES": "Prioridades",
"TAGS": "Tags",
"ASSIGNED_TO": "Atribuído a",
"CREATED_BY": "Criado por",
"CUSTOM_FILTERS": "Filtros personalizados",
"EPIC": "Épico"
},
"CONFIRM_DELETE": {
"TITLE": "Apagar filtro personalizado",
"MESSAGE": "O filtro personalizado '{{customFilterName}}'"
}
}, },
"WYSIWYG": { "WYSIWYG": {
"H1_BUTTON": "Primeira caixa de cabeçalho", "H1_BUTTON": "Primeira caixa de cabeçalho",
@ -228,9 +253,18 @@
"PREVIEW_BUTTON": "Pré Visualizar", "PREVIEW_BUTTON": "Pré Visualizar",
"EDIT_BUTTON": "Editar", "EDIT_BUTTON": "Editar",
"ATTACH_FILE_HELP": "Anexe arquivos arrastando e soltando na área de texto acima.", "ATTACH_FILE_HELP": "Anexe arquivos arrastando e soltando na área de texto acima.",
"ATTACH_FILE_HELP_SAVE_FIRST": "Save first before if you want to attach files by dragging & dropping on the textarea above.",
"MARKDOWN_HELP": "Ajuda de sintaxe markdown" "MARKDOWN_HELP": "Ajuda de sintaxe markdown"
}, },
"PERMISIONS_CATEGORIES": { "PERMISIONS_CATEGORIES": {
"EPICS": {
"NAME": "Épicos",
"VIEW_EPICS": "View epics",
"ADD_EPICS": "Add epics",
"MODIFY_EPICS": "Modify epics",
"COMMENT_EPICS": "Comment epics",
"DELETE_EPICS": "Delete epics"
},
"SPRINTS": { "SPRINTS": {
"NAME": "Sprints", "NAME": "Sprints",
"VIEW_SPRINTS": "Ver sprints", "VIEW_SPRINTS": "Ver sprints",
@ -243,6 +277,7 @@
"VIEW_USER_STORIES": "Ver histórias de usuários", "VIEW_USER_STORIES": "Ver histórias de usuários",
"ADD_USER_STORIES": "Adicionar histórias de usuários", "ADD_USER_STORIES": "Adicionar histórias de usuários",
"MODIFY_USER_STORIES": "Modificar histórias de usuários", "MODIFY_USER_STORIES": "Modificar histórias de usuários",
"COMMENT_USER_STORIES": "Comentar histórias de usuário",
"DELETE_USER_STORIES": "Apagar histórias de usuários" "DELETE_USER_STORIES": "Apagar histórias de usuários"
}, },
"TASKS": { "TASKS": {
@ -250,6 +285,7 @@
"VIEW_TASKS": "Ver tarefas", "VIEW_TASKS": "Ver tarefas",
"ADD_TASKS": "Adicionar uma nova Tarefa", "ADD_TASKS": "Adicionar uma nova Tarefa",
"MODIFY_TASKS": "Modificar tarefa", "MODIFY_TASKS": "Modificar tarefa",
"COMMENT_TASKS": "Comment tasks",
"DELETE_TASKS": "Apagar tarefas" "DELETE_TASKS": "Apagar tarefas"
}, },
"ISSUES": { "ISSUES": {
@ -257,6 +293,7 @@
"VIEW_ISSUES": "Ver problemas", "VIEW_ISSUES": "Ver problemas",
"ADD_ISSUES": "Adicionar problemas", "ADD_ISSUES": "Adicionar problemas",
"MODIFY_ISSUES": "Modificar problemas", "MODIFY_ISSUES": "Modificar problemas",
"COMMENT_ISSUES": "Comment issues",
"DELETE_ISSUES": "Apagar problemas" "DELETE_ISSUES": "Apagar problemas"
}, },
"WIKI": { "WIKI": {
@ -366,6 +403,41 @@
"WATCHING_SECTION": "Observando", "WATCHING_SECTION": "Observando",
"DASHBOARD": "Painel de Projetos" "DASHBOARD": "Painel de Projetos"
}, },
"EPICS": {
"TITLE": "ÉPICOS",
"SECTION_NAME": "Épicos",
"EPIC": "ÉPICO",
"PAGE_TITLE": "Epics - {{projectName}}",
"PAGE_DESCRIPTION": "The epics list of the project {{projectName}}: {{projectDescription}}",
"DASHBOARD": {
"ADD": "+ ADICIONAR ÉPICO",
"UNASSIGNED": "Não-atribuído"
},
"EMPTY": {
"TITLE": "It looks like there aren't any epics yet",
"EXPLANATION": "Epics are items at a higher level that encompass user stories.<br />Epics are at the top of the hierarchy and can be used to group user stories together.",
"HELP": "Saiba mais sobre épicos"
},
"TABLE": {
"VOTES": "Votos",
"NAME": "Nome",
"PROJECT": "Projeto",
"SPRINT": "Sprint",
"ASSIGNED_TO": "Assigned",
"STATUS": "Status",
"PROGRESS": "Progresso",
"VIEW_OPTIONS": "Ver opções"
},
"CREATE": {
"TITLE": "Novo Épico",
"PLACEHOLDER_DESCRIPTION": "Please add descriptive text to help others better understand this epic",
"TEAM_REQUIREMENT": "Team requirement",
"CLIENT_REQUIREMENT": "Client requirement",
"BLOCKED": "Bloqueado",
"BLOCKED_NOTE_PLACEHOLDER": "Por que esse épico está bloqueado?",
"CREATE_EPIC": "Criar épico"
}
},
"PROJECTS": { "PROJECTS": {
"PAGE_TITLE": "Meus projetos - Taiga", "PAGE_TITLE": "Meus projetos - Taiga",
"PAGE_DESCRIPTION": "Uma lista com todos os seus projetos, você pode reorganizá-los ou criar um novo.", "PAGE_DESCRIPTION": "Uma lista com todos os seus projetos, você pode reorganizá-los ou criar um novo.",
@ -402,7 +474,8 @@
"ADMIN": { "ADMIN": {
"COMMON": { "COMMON": {
"TITLE_ACTION_EDIT_VALUE": "Editar valor", "TITLE_ACTION_EDIT_VALUE": "Editar valor",
"TITLE_ACTION_DELETE_VALUE": "Apagar valor" "TITLE_ACTION_DELETE_VALUE": "Apagar valor",
"TITLE_ACTION_DELETE_TAG": "Apagar tag"
}, },
"HELP": "Você precisa de ajuda? Verifique nossa pagina de suporte!", "HELP": "Você precisa de ajuda? Verifique nossa pagina de suporte!",
"PROJECT_DEFAULT_VALUES": { "PROJECT_DEFAULT_VALUES": {
@ -414,8 +487,8 @@
"PAGE_TITLE": "Filiados - {{projectName}}", "PAGE_TITLE": "Filiados - {{projectName}}",
"ADD_BUTTON": "+ Novo Membro", "ADD_BUTTON": "+ Novo Membro",
"ADD_BUTTON_TITLE": "Adicionar novo membro", "ADD_BUTTON_TITLE": "Adicionar novo membro",
"LIMIT_USERS_WARNING_MESSAGE_FOR_ADMIN": "Unfortunately, this project has reached its limit of <strong>({{members}})</strong> allowed members.", "LIMIT_USERS_WARNING_MESSAGE_FOR_ADMIN": "Infelizmente, este projeto atingiu o número máximo de <strong>({{membros}})</strong> membros permitidos.",
"LIMIT_USERS_WARNING_MESSAGE_FOR_OWNER": "This project has reached its limit of <strong>({{members}})</strong> allowed members. If you would like to increase that limit please contact the administrator." "LIMIT_USERS_WARNING_MESSAGE_FOR_OWNER": "Este projeto atingiu o limite de <strong>({{members}})</strong> membros permitidos. Se você deseja aumentar este limite entre em contato com o administrador."
}, },
"PROJECT_EXPORT": { "PROJECT_EXPORT": {
"TITLE": "Exportar", "TITLE": "Exportar",
@ -435,6 +508,8 @@
"TITLE": "Modulos", "TITLE": "Modulos",
"ENABLE": "Habilitar", "ENABLE": "Habilitar",
"DISABLE": "Desabilitar", "DISABLE": "Desabilitar",
"EPICS": "Épicos",
"EPICS_DESCRIPTION": "Visualize and manage the most strategic part of your project",
"BACKLOG": "Backlog", "BACKLOG": "Backlog",
"BACKLOG_DESCRIPTION": "Gerencie suas histórias de usuários para manter uma visualização organizada de trabalhos futuros e priorizados.", "BACKLOG_DESCRIPTION": "Gerencie suas histórias de usuários para manter uma visualização organizada de trabalhos futuros e priorizados.",
"NUMBER_SPRINTS": "Número de sprints esperadas", "NUMBER_SPRINTS": "Número de sprints esperadas",
@ -450,7 +525,7 @@
"MEETUP": "Reunião", "MEETUP": "Reunião",
"MEETUP_DESCRIPTION": "Selecione seu sistema de videoconferência.", "MEETUP_DESCRIPTION": "Selecione seu sistema de videoconferência.",
"SELECT_VIDEOCONFERENCE": "Selecione um sistema de videoconferência", "SELECT_VIDEOCONFERENCE": "Selecione um sistema de videoconferência",
"SALT_CHAT_ROOM": "Add a prefix to the chatroom name", "SALT_CHAT_ROOM": "Adicionar um prefixo ao nome da sala de chat",
"JITSI_CHAT_ROOM": "Jitsi", "JITSI_CHAT_ROOM": "Jitsi",
"APPEARIN_CHAT_ROOM": "AppearIn", "APPEARIN_CHAT_ROOM": "AppearIn",
"TALKY_CHAT_ROOM": "Talky", "TALKY_CHAT_ROOM": "Talky",
@ -474,18 +549,18 @@
"LOGO_HELP": "A imagem deve ser na escala de 80x80px.", "LOGO_HELP": "A imagem deve ser na escala de 80x80px.",
"CHANGE_LOGO": "Alterar logo", "CHANGE_LOGO": "Alterar logo",
"ACTION_USE_DEFAULT_LOGO": "Usar imagem padrão", "ACTION_USE_DEFAULT_LOGO": "Usar imagem padrão",
"MAX_PRIVATE_PROJECTS": "You've reached the maximum number of private projects allowed by your current plan", "MAX_PRIVATE_PROJECTS": "Você atingiu o número máximo de projetos privados permitidos para seu plano atual.",
"MAX_PRIVATE_PROJECTS_MEMBERS": "The maximum number of members for private projects has been exceeded", "MAX_PRIVATE_PROJECTS_MEMBERS": "O número máximo de membros para projetos privados foi excedido.",
"MAX_PUBLIC_PROJECTS": "Unfortunately, you've reached the maximum number of public projects allowed by your current plan", "MAX_PUBLIC_PROJECTS": "Infelizmente você atingiu o número máximo de projetos público permitidos para seu plano atual",
"MAX_PUBLIC_PROJECTS_MEMBERS": "The project exceeds your maximum number of members for public projects", "MAX_PUBLIC_PROJECTS_MEMBERS": "Este projeto atingiu o seu limite atual de membros para projetos públicos",
"PROJECT_OWNER": "Dono do projeto", "PROJECT_OWNER": "Dono do projeto",
"REQUEST_OWNERSHIP": "Solicitar propriedade", "REQUEST_OWNERSHIP": "Solicitar propriedade",
"REQUEST_OWNERSHIP_CONFIRMATION_TITLE": "Gostaria de se tornar o novo dono do projeto?", "REQUEST_OWNERSHIP_CONFIRMATION_TITLE": "Gostaria de se tornar o novo dono do projeto?",
"REQUEST_OWNERSHIP_DESC": "Solicitar ao atual dono de projeto {{name}} a transferência da propriedade deste projeto para você.", "REQUEST_OWNERSHIP_DESC": "Solicitar ao atual dono de projeto {{name}} a transferência da propriedade deste projeto para você.",
"REQUEST_OWNERSHIP_BUTTON": "Solicitação", "REQUEST_OWNERSHIP_BUTTON": "Solicitação",
"REQUEST_OWNERSHIP_SUCCESS": "We'll notify the project owner", "REQUEST_OWNERSHIP_SUCCESS": "Vamos notificar o dono do projeto",
"CHANGE_OWNER": "Change owner", "CHANGE_OWNER": "Mudar dono",
"CHANGE_OWNER_SUCCESS_TITLE": "Ok, your request has been sent!", "CHANGE_OWNER_SUCCESS_TITLE": "Ok, sua requisição foi enviada!",
"CHANGE_OWNER_SUCCESS_DESC": "We will notify you by email if the project ownership request is accepted or declined" "CHANGE_OWNER_SUCCESS_DESC": "We will notify you by email if the project ownership request is accepted or declined"
}, },
"REPORTS": { "REPORTS": {
@ -497,6 +572,7 @@
"REGENERATE_SUBTITLE": "Você está prestes a alterar a url de acesso a dados do CSV. A URL anterior será desabilitada. Você está certo disso?" "REGENERATE_SUBTITLE": "Você está prestes a alterar a url de acesso a dados do CSV. A URL anterior será desabilitada. Você está certo disso?"
}, },
"CSV": { "CSV": {
"SECTION_TITLE_EPIC": "epics reports",
"SECTION_TITLE_US": "Relatórios de histórias de usuários", "SECTION_TITLE_US": "Relatórios de histórias de usuários",
"SECTION_TITLE_TASK": "relatórios de tarefas", "SECTION_TITLE_TASK": "relatórios de tarefas",
"SECTION_TITLE_ISSUE": "relatórios de problemas", "SECTION_TITLE_ISSUE": "relatórios de problemas",
@ -509,6 +585,8 @@
"CUSTOM_FIELDS": { "CUSTOM_FIELDS": {
"TITLE": "Campos Personalizados", "TITLE": "Campos Personalizados",
"SUBTITLE": "Especificar campos personalizados para histórias de usuários, tarefas e problemas", "SUBTITLE": "Especificar campos personalizados para histórias de usuários, tarefas e problemas",
"EPIC_DESCRIPTION": "Epics custom fields",
"EPIC_ADD": "Add a custom field in epics",
"US_DESCRIPTION": "Campos personalizados das histórias de usuários", "US_DESCRIPTION": "Campos personalizados das histórias de usuários",
"US_ADD": "Adicionar campo personalizado nas histórias de usuários", "US_ADD": "Adicionar campo personalizado nas histórias de usuários",
"TASK_DESCRIPTION": "Campos personalizados das Tarefas", "TASK_DESCRIPTION": "Campos personalizados das Tarefas",
@ -534,7 +612,7 @@
"PROJECT_VALUES_PRIORITIES": { "PROJECT_VALUES_PRIORITIES": {
"TITLE": "Prioridades", "TITLE": "Prioridades",
"SUBTITLE": "Especifique as prioridades que seus problemas terão", "SUBTITLE": "Especifique as prioridades que seus problemas terão",
"ISSUE_TITLE": "Prioridades do problema", "ISSUE_TITLE": "Severidade dos apontamentos",
"ACTION_ADD": "Adicionar nova prioridade" "ACTION_ADD": "Adicionar nova prioridade"
}, },
"PROJECT_VALUES_SEVERITIES": { "PROJECT_VALUES_SEVERITIES": {
@ -546,7 +624,8 @@
"PROJECT_VALUES_STATUS": { "PROJECT_VALUES_STATUS": {
"TITLE": "Status", "TITLE": "Status",
"SUBTITLE": "Especifique os status pelos quais suas histórias de usuários, tarefas e problemas passarão", "SUBTITLE": "Especifique os status pelos quais suas histórias de usuários, tarefas e problemas passarão",
"US_TITLE": "Estados das Histórias de Usuários", "EPIC_TITLE": "Epic Statuses",
"US_TITLE": "User Story Statuses",
"TASK_TITLE": "Estados da Tarefa", "TASK_TITLE": "Estados da Tarefa",
"ISSUE_TITLE": "Estados do problema" "ISSUE_TITLE": "Estados do problema"
}, },
@ -556,6 +635,17 @@
"ISSUE_TITLE": "Tipos de problemas", "ISSUE_TITLE": "Tipos de problemas",
"ACTION_ADD": "Adicionar novo {{objName}}" "ACTION_ADD": "Adicionar novo {{objName}}"
}, },
"PROJECT_VALUES_TAGS": {
"TITLE": "Tags",
"SUBTITLE": "View and edit the color of your tags",
"EMPTY": "Atualmente não há tags",
"EMPTY_SEARCH": "Parece que nada foi encontrado com os critérios de sua pesquisa.",
"ACTION_ADD": "Adicionar tag",
"NEW_TAG": "Nova tag",
"MIXING_HELP_TEXT": "Selecione as tags que você quer mesclar",
"MIXING_MERGE": "Mesclar Tags",
"SELECTED": "Selecionado"
},
"ROLES": { "ROLES": {
"PAGE_TITLE": "Funções - {{projectName}}", "PAGE_TITLE": "Funções - {{projectName}}",
"WARNING_NO_ROLE": "Seja cuidadoso, nenhuma função em seu projeto será capaz de estimar o valor dos pontos para as histórias de usuários", "WARNING_NO_ROLE": "Seja cuidadoso, nenhuma função em seu projeto será capaz de estimar o valor dos pontos para as histórias de usuários",
@ -565,7 +655,7 @@
"COUNT_MEMBERS": "{{ role.members_count }} membros com a mesma função", "COUNT_MEMBERS": "{{ role.members_count }} membros com a mesma função",
"TITLE_DELETE_ROLE": "Apagar Função", "TITLE_DELETE_ROLE": "Apagar Função",
"REPLACEMENT_ROLE": "Todos os usuários com essa função serão movidos para", "REPLACEMENT_ROLE": "Todos os usuários com essa função serão movidos para",
"WARNING_DELETE_ROLE": "Be careful! All role estimations will be removed", "WARNING_DELETE_ROLE": "Cuidado! Todas as estimativas de papéis serão removidas",
"ERROR_DELETE_ALL": "Você não pode apagar todos os valores", "ERROR_DELETE_ALL": "Você não pode apagar todos os valores",
"EXTERNAL_USER": "Usuário externo" "EXTERNAL_USER": "Usuário externo"
}, },
@ -588,6 +678,10 @@
"SECTION_NAME": "Github", "SECTION_NAME": "Github",
"PAGE_TITLE": "Github - {{projectName}}" "PAGE_TITLE": "Github - {{projectName}}"
}, },
"GOGS": {
"SECTION_NAME": "Gogs",
"PAGE_TITLE": "Gogs - {{projectName}}"
},
"WEBHOOKS": { "WEBHOOKS": {
"PAGE_TITLE": "Webhooks - {{projectName}}", "PAGE_TITLE": "Webhooks - {{projectName}}",
"SECTION_NAME": "Webhooks", "SECTION_NAME": "Webhooks",
@ -643,13 +737,14 @@
"DEFAULT_DELETE_MESSAGE": "o convite para {{email}}" "DEFAULT_DELETE_MESSAGE": "o convite para {{email}}"
}, },
"DEFAULT_VALUES": { "DEFAULT_VALUES": {
"LABEL_EPIC_STATUS": "Default value for epic status selector",
"LABEL_US_STATUS": "Default value for user story status selector",
"LABEL_POINTS": "Valores padrões para o seletor de pontos", "LABEL_POINTS": "Valores padrões para o seletor de pontos",
"LABEL_US": "Valor padrão para seletor de status da História de Usuário",
"LABEL_TASK_STATUS": "Valor padrão para seletor de status de tarefa", "LABEL_TASK_STATUS": "Valor padrão para seletor de status de tarefa",
"LABEL_PRIORITY": "Valor padão para seletor de prioridade",
"LABEL_SEVERITY": "Valor padrão para seletor de gravidade",
"LABEL_ISSUE_TYPE": "Valor padrão para seletor de tipo de problema ", "LABEL_ISSUE_TYPE": "Valor padrão para seletor de tipo de problema ",
"LABEL_ISSUE_STATUS": "Valor padrão para seletor de status de problema" "LABEL_ISSUE_STATUS": "Valor padrão para seletor de status de problema",
"LABEL_PRIORITY": "Valor padão para seletor de prioridade",
"LABEL_SEVERITY": "Valor padrão para seletor de gravidade"
}, },
"STATUS": { "STATUS": {
"PLACEHOLDER_WRITE_STATUS_NAME": "Digite um nome para o novo status" "PLACEHOLDER_WRITE_STATUS_NAME": "Digite um nome para o novo status"
@ -681,7 +776,8 @@
"PRIORITIES": "Prioridades", "PRIORITIES": "Prioridades",
"SEVERITIES": "Gravidades", "SEVERITIES": "Gravidades",
"TYPES": "Tipos", "TYPES": "Tipos",
"CUSTOM_FIELDS": "Campos personalizados" "CUSTOM_FIELDS": "Campos personalizados",
"TAGS": "Tags"
}, },
"SUBMENU_PROJECT_PROFILE": { "SUBMENU_PROJECT_PROFILE": {
"TITLE": "Perfil do Projeto" "TITLE": "Perfil do Projeto"
@ -695,21 +791,21 @@
"TITLE": "Serviços" "TITLE": "Serviços"
}, },
"PROJECT_TRANSFER": { "PROJECT_TRANSFER": {
"DO_YOU_ACCEPT_PROJECT_OWNERNSHIP": "Would you like to become the new project owner?", "DO_YOU_ACCEPT_PROJECT_OWNERNSHIP": "Você gostaria de se tornar o novo dono do projeto?",
"PRIVATE": "Private", "PRIVATE": "Privado",
"ACCEPTED_PROJECT_OWNERNSHIP": "Congratulations! You're now the new project owner.", "ACCEPTED_PROJECT_OWNERNSHIP": "Parabéns! Você é o proprietário do projeto agora.",
"REJECTED_PROJECT_OWNERNSHIP": "OK. We'll contact the current project owner", "REJECTED_PROJECT_OWNERNSHIP": "OK. Entraremos em contato com o atual dono do projeto.",
"ACCEPT": "Aceitar", "ACCEPT": "Aceitar",
"REJECT": "Reject", "REJECT": "Rejeitar",
"PROPOSE_OWNERSHIP": "<strong>{{owner}}</strong>, the current owner of the project <strong>{{project}}</strong> has asked that you become the new project owner.", "PROPOSE_OWNERSHIP": "<strong>{{owner}}</strong>, the current owner of the project <strong>{{project}}</strong> has asked that you become the new project owner.",
"ADD_COMMENT": "Would you like to add a comment for the project owner?", "ADD_COMMENT": "Would you like to add a comment for the project owner?",
"UNLIMITED_PROJECTS": "Unlimited", "UNLIMITED_PROJECTS": "Ilimitado",
"OWNER_MESSAGE": { "OWNER_MESSAGE": {
"PRIVATE": "Please remember that you can own up to <strong>{{maxProjects}}</strong> private projects. You currently own <strong>{{currentProjects}}</strong> private projects", "PRIVATE": "Please remember that you can own up to <strong>{{maxProjects}}</strong> private projects. You currently own <strong>{{currentProjects}}</strong> private projects",
"PUBLIC": "Please remember that you can own up to <strong>{{maxProjects}}</strong> public projects. You currently own <strong>{{currentProjects}}</strong> public projects" "PUBLIC": "Please remember that you can own up to <strong>{{maxProjects}}</strong> public projects. You currently own <strong>{{currentProjects}}</strong> public projects"
}, },
"CANT_BE_OWNED": "At the moment you cannot become an owner of a project of this type. If you would like to become the owner of this project, please contact the administrator so they change your account settings to enable project ownership.", "CANT_BE_OWNED": "At the moment you cannot become an owner of a project of this type. If you would like to become the owner of this project, please contact the administrator so they change your account settings to enable project ownership.",
"CHANGE_MY_PLAN": "Change my plan" "CHANGE_MY_PLAN": "Mudar meu plano"
} }
}, },
"USER": { "USER": {
@ -751,12 +847,14 @@
"FILTER_TYPE_ALL_TITLE": "Mostrar tudo", "FILTER_TYPE_ALL_TITLE": "Mostrar tudo",
"FILTER_TYPE_PROJECTS": "Projetos", "FILTER_TYPE_PROJECTS": "Projetos",
"FILTER_TYPE_PROJECT_TITLES": "Mostrar somente projetos", "FILTER_TYPE_PROJECT_TITLES": "Mostrar somente projetos",
"FILTER_TYPE_EPICS": "Épicos",
"FILTER_TYPE_EPIC_TITLES": "Show only epics",
"FILTER_TYPE_USER_STORIES": "Histórias", "FILTER_TYPE_USER_STORIES": "Histórias",
"FILTER_TYPE_USER_STORIES_TITLES": "Mostrar apenas histórias de usuários", "FILTER_TYPE_USER_STORIES_TITLES": "Mostrar apenas histórias de usuários",
"FILTER_TYPE_TASKS": "Tarefas", "FILTER_TYPE_TASKS": "Tarefas",
"FILTER_TYPE_TASK_TITLES": "Mostrar apenas tarefas", "FILTER_TYPE_TASK_TITLES": "Mostrar apenas tarefas",
"FILTER_TYPE_ISSUES": "Problemas", "FILTER_TYPE_ISSUES": "Problemas",
"FILTER_TYPE_ISSUES_TITLE": "mostrar apenas problemas", "FILTER_TYPE_ISSUES_TITLE": "mostrar apenas apontamentos",
"EMPTY_TITLE": "Parece que não há nada para exibir aqui." "EMPTY_TITLE": "Parece que não há nada para exibir aqui."
} }
}, },
@ -772,8 +870,8 @@
"MEMBERS_COUNTER_TITLE": "{total, plural, one{one member} other{# members}}", "MEMBERS_COUNTER_TITLE": "{total, plural, one{one member} other{# members}}",
"BLOCKED_PROJECT": { "BLOCKED_PROJECT": {
"BLOCKED": "Projeto bloqueado", "BLOCKED": "Projeto bloqueado",
"THIS_PROJECT_IS_BLOCKED": "This project is temporarily blocked", "THIS_PROJECT_IS_BLOCKED": "Este projeto está temporariamente bloqueado",
"TO_UNBLOCK_CONTACT_THE_ADMIN_STAFF": "In order to unblock your projects, contact the administrator." "TO_UNBLOCK_CONTACT_THE_ADMIN_STAFF": "Para desbloquear seus projetos, contate o administrador."
}, },
"STATS": { "STATS": {
"PROJECT": "projetos<br/> pontos", "PROJECT": "projetos<br/> pontos",
@ -838,7 +936,7 @@
"ERROR_MAX_SIZE_EXCEEDED": "'{{fileName}}' ({{fileSize}}) é muito pesado para nossos Oompa Loompas, tente algo menor que ({{maxFileSize}})", "ERROR_MAX_SIZE_EXCEEDED": "'{{fileName}}' ({{fileSize}}) é muito pesado para nossos Oompa Loompas, tente algo menor que ({{maxFileSize}})",
"SYNC_SUCCESS": "Seu projeto foi importado com sucesso", "SYNC_SUCCESS": "Seu projeto foi importado com sucesso",
"PROJECT_RESTRICTIONS": { "PROJECT_RESTRICTIONS": {
"PROJECT_MEMBERS_DESC": "The project you are trying to import has {{members}} members, unfortunately, your current plan allows for a maximum of {{max_memberships}} members per project. If you would like to increase that limit please contact the administrator.", "PROJECT_MEMBERS_DESC": "O projeto que você está tentando importar tem {{members}} membros e infelizmente seu plano atual tem um limite máximo de {{max_memberships}} membros por projeto. Se você deseja aumentar este limite entre em contato com o administrador.",
"PRIVATE_PROJECTS_SPACE": { "PRIVATE_PROJECTS_SPACE": {
"TITLE": "Unfortunately, your current plan does not allow for additional private projects", "TITLE": "Unfortunately, your current plan does not allow for additional private projects",
"DESC": "The project you are trying to import is private. Unfortunately, your current plan does not allow for additional private projects." "DESC": "The project you are trying to import is private. Unfortunately, your current plan does not allow for additional private projects."
@ -855,7 +953,7 @@
}, },
"PRIVATE_PROJECTS_SPACE_MEMBERS": { "PRIVATE_PROJECTS_SPACE_MEMBERS": {
"TITLE": "Unfortunately your current plan doesn't allow additional private projects or an increase of more than {{max_memberships}} members per private project", "TITLE": "Unfortunately your current plan doesn't allow additional private projects or an increase of more than {{max_memberships}} members per private project",
"DESC": "The project that you are trying to import is private and has {{members}} members." "DESC": "O projeto que você está tentando importar é privado e tem {{members}} membros."
}, },
"PUBLIC_PROJECTS_SPACE_MEMBERS": { "PUBLIC_PROJECTS_SPACE_MEMBERS": {
"TITLE": "Unfortunately your current plan doesn't allow additional public projects or an increase of more than {{max_memberships}} members per public project", "TITLE": "Unfortunately your current plan doesn't allow additional public projects or an increase of more than {{max_memberships}} members per public project",
@ -892,7 +990,7 @@
"NEWSLETTER_LABEL_TEXT": "Eu não quero receber mais os informativos", "NEWSLETTER_LABEL_TEXT": "Eu não quero receber mais os informativos",
"CANCEL": "Voltar para configurações", "CANCEL": "Voltar para configurações",
"ACCEPT": "Remover conta", "ACCEPT": "Remover conta",
"BLOCK_PROJECT": "Note that all the projects you own projects will be <strong>blocked</strong> after you delete your account. If you do want a project blocked, transfer ownership to another member of each project prior to deleting your account.", "BLOCK_PROJECT": "Note que todos os projetos em que você é o dono serão <strong>bloqueados</strong> depois que você apagar sua conta. Se você quer um projeto bloqueado, transfira a posse para outro membro de cada projeto antes de apagar sua conta.",
"SUBTITLE": "É uma pena vê-lo partir. Estaremos aqui se você algum dia considerar-nos novamente! :(" "SUBTITLE": "É uma pena vê-lo partir. Estaremos aqui se você algum dia considerar-nos novamente! :("
}, },
"DELETE_PROJECT": { "DELETE_PROJECT": {
@ -950,18 +1048,18 @@
"CREATE_MEMBER": { "CREATE_MEMBER": {
"PLACEHOLDER_INVITATION_TEXT": "(Opcional) Adicione uma mensagem de texto ao convite. Diga algo animador para os novos membros ;-)", "PLACEHOLDER_INVITATION_TEXT": "(Opcional) Adicione uma mensagem de texto ao convite. Diga algo animador para os novos membros ;-)",
"PLACEHOLDER_TYPE_EMAIL": "Digite um Email", "PLACEHOLDER_TYPE_EMAIL": "Digite um Email",
"LIMIT_USERS_WARNING_MESSAGE_FOR_OWNER": "Unfortunately, this project can't have more than <strong>{{maxMembers}}</strong> members.<br> If you would like to increase the current limit, please contact the administrator.", "LIMIT_USERS_WARNING_MESSAGE_FOR_OWNER": "You are about to reach the maximum number of members allowed for this project, <strong>{{maxMembers}}</strong> members. If you would like to increase the current limit, please contact the administrator.",
"LIMIT_USERS_WARNING_MESSAGE": "Unfortunately, this project can't have more than <strong>{{maxMembers}}</strong> members." "LIMIT_USERS_WARNING_MESSAGE": "You are about to reach the maximum number of members allowed for this project, <strong>{{maxMembers}}</strong> members."
}, },
"LEAVE_PROJECT_WARNING": { "LEAVE_PROJECT_WARNING": {
"TITLE": "Unfortunately, this project can't be left without an owner", "TITLE": "Infelizmente, este projeto não pode ficar sem um dono",
"CURRENT_USER_OWNER": { "CURRENT_USER_OWNER": {
"DESC": "You are the current owner of this project. Before leaving, please transfer ownership to someone else.", "DESC": "Você é o dono atual deste projeto. Antes de sair, por favor transfira o projeto para outra pessoa.",
"BUTTON": "Change the project owner" "BUTTON": "Mude o dono do projeto"
}, },
"OTHER_USER_OWNER": { "OTHER_USER_OWNER": {
"DESC": "Unfortunately, you can't delete a member who is also the current project owner. First, please assign a new project owner.", "DESC": "Infelizmnete, você não pode apagar um membro que também é o dono de um projeto. Primeiro designe um novo proprietário para o projeto.",
"BUTTON": "Request project owner change" "BUTTON": "Solicite a mudança do dono do projeto"
} }
}, },
"CHANGE_OWNER": { "CHANGE_OWNER": {
@ -970,28 +1068,57 @@
"BUTTON": "Pedir a este membro do projeto para se tornar o novo dono do projeto" "BUTTON": "Pedir a este membro do projeto para se tornar o novo dono do projeto"
} }
}, },
"EPIC": {
"PAGE_TITLE": "{{epicSubject}} - Epic {{epicRef}} - {{projectName}}",
"PAGE_DESCRIPTION": "Status: {{epicStatus }}. Description: {{epicDescription}}",
"SECTION_NAME": "Épico",
"TITLE_LIGHTBOX_UNLINK_RELATED_USERSTORY": "Unlink related userstory",
"MSG_LIGHTBOX_UNLINK_RELATED_USERSTORY": "It will delete the link to the related userstory '{{subject}}'",
"ERROR_UNLINK_RELATED_USERSTORY": "We have not been able to unlink: {{errorMessage}}",
"CREATE_RELATED_USERSTORIES": "Create a relationship with",
"NEW_USERSTORY": "Nova história de usuário",
"EXISTING_USERSTORY": "Existing user story",
"CHOOSE_PROJECT_FOR_CREATION": "What's the project?",
"SUBJECT": "Assunto",
"SUBJECT_BULK_MODE": "Subject (bulk insert)",
"CHOOSE_PROJECT_FROM": "What's the project?",
"CHOOSE_USERSTORY": "What's the user story?",
"NO_USERSTORIES": "This project has no User Stories yet. Please select another project.",
"FILTER_USERSTORIES": "Filter user stories",
"LIGHTBOX_TITLE_BLOKING_EPIC": "Blocking epic",
"ACTION_DELETE": "Delete epic"
},
"US": { "US": {
"PAGE_TITLE": "{{userStorySubject}} - História de Usuário {{userStoryRef}} - {{projectName}}", "PAGE_TITLE": "{{userStorySubject}} - História de Usuário {{userStoryRef}} - {{projectName}}",
"PAGE_DESCRIPTION": "Estado: {{userStoryStatus }}. Completos {{userStoryProgressPercentage}}% ({{userStoryClosedTasks}} de {{userStoryTotalTasks}} tarefas encerradas). Pontos: {{userStoryPoints}}. Descrição: {{userStoryDescription}}", "PAGE_DESCRIPTION": "Estado: {{userStoryStatus }}. Completos {{userStoryProgressPercentage}}% ({{userStoryClosedTasks}} de {{userStoryTotalTasks}} tarefas encerradas). Pontos: {{userStoryPoints}}. Descrição: {{userStoryDescription}}",
"SECTION_NAME": "Detalhes da História de Usuário", "SECTION_NAME": "História de usuário",
"LINK_TASKBOARD": "Quadro de Tarefas", "LINK_TASKBOARD": "Quadro de Tarefas",
"TITLE_LINK_TASKBOARD": "Ir para o quadro de tarefas", "TITLE_LINK_TASKBOARD": "Ir para o quadro de tarefas",
"TOTAL_POINTS": "total de pontos", "TOTAL_POINTS": "total de pontos",
"ADD": "+ Adicionar uma nova História de Usuário", "ADD": "+ Adicionar uma nova História de Usuário",
"ADD_BULK": "Adicionar Histórias de Usuários em lote", "ADD_BULK": "Adicionar Histórias de Usuários em lote",
"PROMOTED": "Esta história de usuário foi promovida do problema:", "PROMOTED": "Esta História de Usuário foi criada a partir do Problema:",
"TITLE_LINK_GO_TO_ISSUE": "Ir para problema", "TITLE_LINK_GO_TO_ISSUE": "Adicionar comentários aos apontamentos",
"EXTERNAL_REFERENCE": "Esta História de Usuário foi criada de", "EXTERNAL_REFERENCE": "Esta História de Usuário foi criada de",
"GO_TO_EXTERNAL_REFERENCE": "Ir para a origem", "GO_TO_EXTERNAL_REFERENCE": "Ir para a origem",
"BLOCKED": "Esta história de usuário está bloqueada", "BLOCKED": "Esta história de usuário está bloqueada",
"PREVIOUS": "história de usuário anterior",
"NEXT": "proxima história de usuário",
"TITLE_DELETE_ACTION": "Apagar história de usuário", "TITLE_DELETE_ACTION": "Apagar história de usuário",
"LIGHTBOX_TITLE_BLOKING_US": "História de usuário bloqueadora", "LIGHTBOX_TITLE_BLOKING_US": "História de usuário bloqueadora",
"TASK_COMPLETED": "{{totalClosedTasks}}/{{totalTasks}} tarefas completas", "TASK_COMPLETED": "{{totalClosedTasks}}/{{totalTasks}} tarefas completas",
"ASSIGN": "Atribuir História de Usuário", "ASSIGN": "Atribuir História de Usuário",
"NOT_ESTIMATED": "Não estimado", "NOT_ESTIMATED": "Não estimado",
"TOTAL_US_POINTS": "Total de pontos de histórias", "TOTAL_US_POINTS": "Total de pontos de histórias",
"TRIBE": {
"PUBLISH": "Publicar como Gig no Taiga Tribe",
"PUBLISH_INFO": "Mais informações",
"PUBLISH_TITLE": "Mais informações sobre como publicar na Tribo Taiga",
"PUBLISHED_AS_GIG": "Story published as Gig in Taiga Tribe",
"EDIT_LINK": "Editar link",
"CLOSE": "Fechar",
"SYNCHRONIZE_LINK": "sincronizar com a Tribo Taiga",
"PUBLISH_MORE_INFO_TITLE": "Você precisa de alguém para esta tarefa?",
"PUBLISH_MORE_INFO_TEXT": "<p>If you need help with a particular piece of work you can easily create gigs on<a href='taigatribe.com' title='Taiga Tribe'> Taiga Tribe </a> and receive help from all over the world. You will be able to control and manage the gig enjoying a great community eager to contribute.</p><p><a href='taigatribe.com' title='Taiga Tribe'> TaigaTribe </a> was born as a Taiga sibling. Both platforms can live separately but we believe that there is much power in using them combined so we are making sure the integration works like a charm.</p>"
},
"FIELDS": { "FIELDS": {
"TEAM_REQUIREMENT": "Requisitos da Equipe", "TEAM_REQUIREMENT": "Requisitos da Equipe",
"CLIENT_REQUIREMENT": "Requisitos do Cliente", "CLIENT_REQUIREMENT": "Requisitos do Cliente",
@ -999,28 +1126,47 @@
} }
}, },
"COMMENTS": { "COMMENTS": {
"DELETED_INFO": "Comentário apagado por {{user}} em {{date}}", "DELETED_INFO": "Comentário apagado por {{user}}",
"TITLE": "Comentários", "TITLE": "Comentários",
"COMMENTS_COUNT": "{{comments}} comentários",
"ORDER": "Ordenação",
"OLDER_FIRST": "Antigos primeiro",
"RECENT_FIRST": "Recentes primeiro",
"COMMENT": "Comentário", "COMMENT": "Comentário",
"EDIT_COMMENT": "Editar comentário",
"EDITED_COMMENT": "Editado:",
"SHOW_HISTORY": "Ver histórico",
"TYPE_NEW_COMMENT": "Escreva um novo comentário aqui", "TYPE_NEW_COMMENT": "Escreva um novo comentário aqui",
"SHOW_DELETED": "Mostrar comentários apagados", "SHOW_DELETED": "Mostrar comentários apagados",
"HIDE_DELETED": "Esconder comentário apagado", "HIDE_DELETED": "Esconder comentário apagado",
"DELETE": "Apagar comentário", "DELETE": "Apagar comentário",
"RESTORE": "Restaurar comentário" "RESTORE": "Restaurar comentário",
"HISTORY": {
"TITLE": "Atividade"
}
}, },
"ACTIVITY": { "ACTIVITY": {
"SHOW_ACTIVITY": "Exibir atividade", "SHOW_ACTIVITY": "Exibir atividade",
"DATETIME": "DD MMM YYYY HH:mm", "DATETIME": "DD MMM YYYY HH:mm",
"SHOW_MORE": "+ Mostrar entradas anteriores (mais {{showMore}})", "SHOW_MORE": "+ Mostrar entradas anteriores (mais {{showMore}})",
"TITLE": "Atividade", "TITLE": "Atividade",
"ACTIVITIES_COUNT": "{{activities}} atividades",
"REMOVED": "removido", "REMOVED": "removido",
"ADDED": "adicionado", "ADDED": "adicionado",
"US_POINTS": "pontos de história ({{name}})", "TAGS_ADDED": "tags adicionadas:",
"NEW_ATTACHMENT": "novo anexo", "TAGS_REMOVED": "tags removidas:",
"DELETED_ATTACHMENT": "apagar anexo", "US_POINTS": "{{role}} pontos",
"UPDATED_ATTACHMENT": "anexo atualizado {{filename}}", "NEW_ATTACHMENT": "novo anexo:",
"DELETED_CUSTOM_ATTRIBUTE": "atributo personalizado apagado", "DELETED_ATTACHMENT": "anexo apagado:",
"UPDATED_ATTACHMENT": "anexo atualizado ({{filename}}):",
"CREATED_CUSTOM_ATTRIBUTE": "atributo personalizado criado",
"UPDATED_CUSTOM_ATTRIBUTE": "atributo personalizado atualizado",
"SIZE_CHANGE": "Feito {size, plural, one{one change} other{# changes}}", "SIZE_CHANGE": "Feito {size, plural, one{one change} other{# changes}}",
"BECAME_DEPRECATED": "foi depreciado",
"BECAME_UNDEPRECATED": "foi depreciado",
"TEAM_REQUIREMENT": "Requisitos da Equipe",
"CLIENT_REQUIREMENT": "Requisitos do Cliente",
"BLOCKED": "Bloqueado",
"VALUES": { "VALUES": {
"YES": "sim", "YES": "sim",
"NO": "não", "NO": "não",
@ -1052,12 +1198,14 @@
"TAGS": "tags", "TAGS": "tags",
"ATTACHMENTS": "anexos", "ATTACHMENTS": "anexos",
"IS_DEPRECATED": "está obsoleto", "IS_DEPRECATED": "está obsoleto",
"IS_NOT_DEPRECATED": "is not deprecated",
"ORDER": "ordem", "ORDER": "ordem",
"BACKLOG_ORDER": "requisição do backlog", "BACKLOG_ORDER": "requisição do backlog",
"SPRINT_ORDER": "ordem de sprint ", "SPRINT_ORDER": "ordem de sprint ",
"KANBAN_ORDER": "pedido kanban", "KANBAN_ORDER": "pedido kanban",
"TASKBOARD_ORDER": "Ordem de quadro de tarefa", "TASKBOARD_ORDER": "Ordem de quadro de tarefa",
"US_ORDER": "ordem da história de usuário" "US_ORDER": "ordem da história de usuário",
"COLOR": "cor"
} }
}, },
"BACKLOG": { "BACKLOG": {
@ -1109,7 +1257,8 @@
"CLOSED_TASKS": "tarefas<br />fechadas", "CLOSED_TASKS": "tarefas<br />fechadas",
"IOCAINE_DOSES": "iocaine<br />doses", "IOCAINE_DOSES": "iocaine<br />doses",
"SHOW_STATISTICS_TITLE": "Mostrar estatísticas", "SHOW_STATISTICS_TITLE": "Mostrar estatísticas",
"TOGGLE_BAKLOG_GRAPH": "Mostrar/Esconder gráfico de burndown" "TOGGLE_BAKLOG_GRAPH": "Mostrar/Esconder gráfico de burndown",
"POINTS_PER_ROLE": "Points per role"
}, },
"SUMMARY": { "SUMMARY": {
"PROJECT_POINTS": "pontos do<br />projeto", "PROJECT_POINTS": "pontos do<br />projeto",
@ -1122,9 +1271,7 @@
"TITLE": "Filtros", "TITLE": "Filtros",
"REMOVE": "Remover filtros", "REMOVE": "Remover filtros",
"HIDE": "Esconder Filtros", "HIDE": "Esconder Filtros",
"SHOW": "Mostrar Filtros", "SHOW": "Mostrar Filtros"
"FILTER_CATEGORY_STATUS": "Status",
"FILTER_CATEGORY_TAGS": "Tags"
}, },
"SPRINTS": { "SPRINTS": {
"TITLE": "SPRINTS", "TITLE": "SPRINTS",
@ -1179,7 +1326,7 @@
"TASK": { "TASK": {
"PAGE_TITLE": "{{taskSubject}} - Tarefa {{taskRef}} - {{projectName}}", "PAGE_TITLE": "{{taskSubject}} - Tarefa {{taskRef}} - {{projectName}}",
"PAGE_DESCRIPTION": "Estado: {{taskStatus }}. Descrição: {{taskDescription}}", "PAGE_DESCRIPTION": "Estado: {{taskStatus }}. Descrição: {{taskDescription}}",
"SECTION_NAME": "Detalhes da Tarefa", "SECTION_NAME": "Tarefa",
"LINK_TASKBOARD": "Quadro de Tarefas", "LINK_TASKBOARD": "Quadro de Tarefas",
"TITLE_LINK_TASKBOARD": "Ir para o quadro de tarefas", "TITLE_LINK_TASKBOARD": "Ir para o quadro de tarefas",
"PLACEHOLDER_SUBJECT": "Digite um novo titulo para tarefa", "PLACEHOLDER_SUBJECT": "Digite um novo titulo para tarefa",
@ -1189,8 +1336,6 @@
"ORIGIN_US": "Essa tarefa foi criada a partir de", "ORIGIN_US": "Essa tarefa foi criada a partir de",
"TITLE_LINK_GO_ORIGIN": "Ir para história de usuário", "TITLE_LINK_GO_ORIGIN": "Ir para história de usuário",
"BLOCKED": "Esta tarefa está bloqueada", "BLOCKED": "Esta tarefa está bloqueada",
"PREVIOUS": "tarefa anterior",
"NEXT": "nova tarefa",
"TITLE_DELETE_ACTION": "Apagar Tarefa", "TITLE_DELETE_ACTION": "Apagar Tarefa",
"LIGHTBOX_TITLE_BLOKING_TASK": "Tarefa bloqueadora", "LIGHTBOX_TITLE_BLOKING_TASK": "Tarefa bloqueadora",
"FIELDS": { "FIELDS": {
@ -1225,19 +1370,16 @@
"SUCCESS": "Nossos Oompa Loompas atualizaram seu email" "SUCCESS": "Nossos Oompa Loompas atualizaram seu email"
}, },
"ISSUES": { "ISSUES": {
"PAGE_TITLE": "Problemas - {{projectName}}", "PAGE_TITLE": "Apontamentos - {{projectName}}",
"PAGE_DESCRIPTION": "O painel de problemas do projeto {{projectName}}: {{projectDescription}}", "PAGE_DESCRIPTION": "O painel de problemas do projeto {{projectName}}: {{projectDescription}}",
"LIST_SECTION_NAME": "Problemas", "LIST_SECTION_NAME": "Tipos de problemas",
"SECTION_NAME": "Detalhes do problema", "SECTION_NAME": "Problema",
"ACTION_NEW_ISSUE": "+ NOVO PROBLEMA", "ACTION_NEW_ISSUE": "+ NOVO PROBLEMA",
"ACTION_PROMOTE_TO_US": "Promover para História de Usuário", "ACTION_PROMOTE_TO_US": "Promover para História de Usuário",
"PLACEHOLDER_FILTER_NAME": "Digite o nome do filtro e pressione Enter",
"PROMOTED": "Esse problema foi promovido para história de usuário", "PROMOTED": "Esse problema foi promovido para história de usuário",
"EXTERNAL_REFERENCE": "Esse problema foi criado a partir de", "EXTERNAL_REFERENCE": "Esse problema foi criado a partir de",
"GO_TO_EXTERNAL_REFERENCE": "Ir para a origem", "GO_TO_EXTERNAL_REFERENCE": "Ir para a origem",
"BLOCKED": "Esse problema está bloqueado", "BLOCKED": "Esse apontamento está bloqueado",
"TITLE_PREVIOUS_ISSUE": "problema anterior",
"TITLE_NEXT_ISSUE": "próximo problema",
"ACTION_DELETE": "Problema apagado", "ACTION_DELETE": "Problema apagado",
"LIGHTBOX_TITLE_BLOKING_ISSUE": "Problema que está bloqueando", "LIGHTBOX_TITLE_BLOKING_ISSUE": "Problema que está bloqueando",
"FIELDS": { "FIELDS": {
@ -1249,28 +1391,6 @@
"TITLE": "Promover esse problema para nova história de usuário", "TITLE": "Promover esse problema para nova história de usuário",
"MESSAGE": "Você tem certeza que deseja criar uma nova História de Usuário a partir desse problema?" "MESSAGE": "Você tem certeza que deseja criar uma nova História de Usuário a partir desse problema?"
}, },
"FILTERS": {
"TITLE": "Filtros",
"INPUT_SEARCH_PLACEHOLDER": "Assunto ou ref",
"TITLE_ACTION_SEARCH": "Procurar",
"ACTION_SAVE_CUSTOM_FILTER": "salve como filtro personalizado",
"BREADCRUMB": "Filtros",
"TITLE_BREADCRUMB": "Filtros",
"CATEGORIES": {
"TYPE": "Tipo",
"STATUS": "Status",
"SEVERITY": "Gravidade",
"PRIORITIES": "Prioridades",
"TAGS": "Tags",
"ASSIGNED_TO": "Atribuído a",
"CREATED_BY": "Criado por",
"CUSTOM_FILTERS": "Filtros personalizados"
},
"CONFIRM_DELETE": {
"TITLE": "Apagar filtro personalizado",
"MESSAGE": "O filtro personalizado '{{customFilterName}}'"
}
},
"TABLE": { "TABLE": {
"COLUMNS": { "COLUMNS": {
"TYPE": "Tipo", "TYPE": "Tipo",
@ -1316,6 +1436,7 @@
"SEARCH": { "SEARCH": {
"PAGE_TITLE": "Buscar - {{projectName}}", "PAGE_TITLE": "Buscar - {{projectName}}",
"PAGE_DESCRIPTION": "Busque qualquer coisa, histórias de usuários, problemas, tarefas, ou páginas da wiki, no projeto {{projectName}}: {{projectDescription}}", "PAGE_DESCRIPTION": "Busque qualquer coisa, histórias de usuários, problemas, tarefas, ou páginas da wiki, no projeto {{projectName}}: {{projectDescription}}",
"FILTER_EPICS": "Épicos",
"FILTER_USER_STORIES": "Histórias de Usuários", "FILTER_USER_STORIES": "Histórias de Usuários",
"FILTER_ISSUES": "Problemas", "FILTER_ISSUES": "Problemas",
"FILTER_TASKS": "Tarefas", "FILTER_TASKS": "Tarefas",
@ -1332,7 +1453,7 @@
"APP_TITLE": "EQUIPE - {{projectName}}", "APP_TITLE": "EQUIPE - {{projectName}}",
"PLACEHOLDER_INPUT_SEARCH": "Procurar pelo nome completo...", "PLACEHOLDER_INPUT_SEARCH": "Procurar pelo nome completo...",
"COLUMN_MR_WOLF": "Sr. Wolf", "COLUMN_MR_WOLF": "Sr. Wolf",
"EXPLANATION_COLUMN_MR_WOLF": "Problemas fechados", "EXPLANATION_COLUMN_MR_WOLF": "Adicionar apontamentos",
"COLUMN_IOCAINE": "Bebedor de Iocaine", "COLUMN_IOCAINE": "Bebedor de Iocaine",
"EXPLANATION_COLUMN_IOCAINE": "Doses de Iocaine ingeridas", "EXPLANATION_COLUMN_IOCAINE": "Doses de Iocaine ingeridas",
"COLUMN_CERVANTES": "Pero Vaz de Caminha", "COLUMN_CERVANTES": "Pero Vaz de Caminha",
@ -1397,7 +1518,7 @@
"WIZARD": { "WIZARD": {
"SECTION_TITLE_CREATE_PROJECT": "Criar Projeto", "SECTION_TITLE_CREATE_PROJECT": "Criar Projeto",
"CREATE_PROJECT_TEXT": "Novo em folha. Tão excitante!", "CREATE_PROJECT_TEXT": "Novo em folha. Tão excitante!",
"CHOOSE_TEMPLATE": "Which template fits your project best?", "CHOOSE_TEMPLATE": "Qual template se encaixa melhor no seu projeto?",
"CHOOSE_TEMPLATE_TITLE": "Mais informações sobre templates de projeto", "CHOOSE_TEMPLATE_TITLE": "Mais informações sobre templates de projeto",
"CHOOSE_TEMPLATE_INFO": "Mais informações", "CHOOSE_TEMPLATE_INFO": "Mais informações",
"PROJECT_DETAILS": "Detalhes do Projeto", "PROJECT_DETAILS": "Detalhes do Projeto",
@ -1405,7 +1526,7 @@
"PRIVATE_PROJECT": "Projeto Privado", "PRIVATE_PROJECT": "Projeto Privado",
"CREATE_PROJECT": "Criar projeto", "CREATE_PROJECT": "Criar projeto",
"MAX_PRIVATE_PROJECTS": "You've reached the maximum number of private projects", "MAX_PRIVATE_PROJECTS": "You've reached the maximum number of private projects",
"MAX_PUBLIC_PROJECTS": "Unfortunately, you've reached the maximum number of public projects", "MAX_PUBLIC_PROJECTS": "Infelizmente, você atingiu o número máximo de projetos públicos",
"CHANGE_PLANS": "change plans" "CHANGE_PLANS": "change plans"
}, },
"WIKI": { "WIKI": {
@ -1417,13 +1538,24 @@
"DELETE_LIGHTBOX_TITLE": "Apagar página Wiki", "DELETE_LIGHTBOX_TITLE": "Apagar página Wiki",
"DELETE_LINK_TITLE": "Remover link de Wiki", "DELETE_LINK_TITLE": "Remover link de Wiki",
"NAVIGATION": { "NAVIGATION": {
"SECTION_NAME": "Links", "HOME": "Página principal",
"ACTION_ADD_LINK": "Adicionar link" "SECTION_NAME": "BOOKMARKS",
"ACTION_ADD_LINK": "Add bookmark",
"ALL_PAGES": "Todas as páginas wiki"
}, },
"SUMMARY": { "SUMMARY": {
"TIMES_EDITED": "vezes<br />editadas", "TIMES_EDITED": "vezes<br />editadas",
"LAST_EDIT": "última<br />edição", "LAST_EDIT": "última<br />edição",
"LAST_MODIFICATION": "ultima modificação" "LAST_MODIFICATION": "ultima modificação"
},
"SECTION_PAGES_LIST": "Todas as páginas",
"PAGES_LIST_COLUMNS": {
"TITLE": "Título",
"EDITIONS": "Edições",
"CREATED": "Criado",
"MODIFIED": "Modificado",
"CREATOR": "Criador",
"LAST_MODIFIER": "Último modificador"
} }
}, },
"HINTS": { "HINTS": {
@ -1447,21 +1579,27 @@
"TASK_CREATED_WITH_US": "{{username}} criou nova tarefa {{obj_name}} em {{project_name}} que pertence a História de Usuário {{us_name}}", "TASK_CREATED_WITH_US": "{{username}} criou nova tarefa {{obj_name}} em {{project_name}} que pertence a História de Usuário {{us_name}}",
"WIKI_CREATED": "{{username}} criou uma página wiki {{obj_name}} em {{project_name}}", "WIKI_CREATED": "{{username}} criou uma página wiki {{obj_name}} em {{project_name}}",
"MILESTONE_CREATED": "{{username}} criou uma nova sprint {{obj_name}} em {{project_name}}", "MILESTONE_CREATED": "{{username}} criou uma nova sprint {{obj_name}} em {{project_name}}",
"EPIC_CREATED": "{{username}} has created a new epic {{obj_name}} in {{project_name}}",
"EPIC_RELATED_USERSTORY_CREATED": "{{username}} has related the userstory {{related_us_name}} to the epic {{epic_name}} in {{project_name}}",
"NEW_PROJECT": "{{username}} criou o projeto {{project_name}}", "NEW_PROJECT": "{{username}} criou o projeto {{project_name}}",
"MILESTONE_UPDATED": "{{username}} atualizou a sprint {{obj_name}}", "MILESTONE_UPDATED": "{{username}} atualizou a sprint {{obj_name}}",
"US_UPDATED": "{{username}} atualizou o atributo \"{{field_name}}\" da História de Usuário {{obj_name}}", "US_UPDATED": "{{username}} atualizou o atributo \"{{field_name}}\" da História de Usuário {{obj_name}}",
"US_UPDATED_WITH_NEW_VALUE": "{{username}} atualizou o trabalho \"{{field_name}}\" da US {{obj_name}} para {{new_value}}", "US_UPDATED_WITH_NEW_VALUE": "{{username}} atualizou o atributo \"{{field_name}}\" da História de Usuário {{obj_name}} para {{new_value}}",
"US_UPDATED_POINTS": "{{username}} atualizou pontos de '{{role_name}}' da História de Usuário {{obj_name}} para {{new_value}}", "US_UPDATED_POINTS": "{{username}} atualizou os pontos de '{{role_name}}' da História de Usuário {{obj_name}} para {{new_value}}",
"ISSUE_UPDATED": "{{username}} atualizou o atributo \"{{field_name}}\" do problema {{obj_name}}", "ISSUE_UPDATED": "{{username}} atualizou o atributo \"{{field_name}}\" do problema {{obj_name}}",
"ISSUE_UPDATED_WITH_NEW_VALUE": "{{username}} atualizou o atributo \"{{field_name}}\" do problema {{obj_name}} para {{new_value}}", "ISSUE_UPDATED_WITH_NEW_VALUE": "{{username}} atualizou o atributo \"{{field_name}}\" do problema {{obj_name}} para {{new_value}}",
"TASK_UPDATED": "{{username}} atualizou o atributo \"{{field_name}}\" da tarefa {{obj_name}} para {{new_value}}", "TASK_UPDATED": "{{username}} atualizou o atributo \"{{field_name}}\" da tarefa {{obj_name}} para {{new_value}}",
"TASK_UPDATED_WITH_NEW_VALUE": "{{username}} Atualizou o atributo \"{{field_name}}\" da tarefa {{obj_name}} para {{new_value}}", "TASK_UPDATED_WITH_NEW_VALUE": "{{username}} atualizou o atributo \"{{field_name}}\" da tarefa {{obj_name}} para {{new_value}}",
"TASK_UPDATED_WITH_US": "{{username}} atualizou o atributo \"{{field_name}}\" da tarefa {{obj_name}} que pertence à História de Usuário {{us_name}}", "TASK_UPDATED_WITH_US": "{{username}} atualizou o atributo \"{{field_name}}\" da tarefa {{obj_name}} que pertence à História de Usuário {{us_name}}",
"TASK_UPDATED_WITH_US_NEW_VALUE": "{{username}} atualizou o atributo \"{{field_name}}\" da tarefa {{obj_name}} que pertence à História de Usuário {{us_name}} para {{new_value}}", "TASK_UPDATED_WITH_US_NEW_VALUE": "{{username}} atualizou o atributo \"{{field_name}}\" da tarefa {{obj_name}} que pertence à História de Usuário {{us_name}} para {{new_value}}",
"WIKI_UPDATED": "{{username}} atualizou a página wiki {{obj_name}}", "WIKI_UPDATED": "{{username}} atualizou a página wiki {{obj_name}}",
"EPIC_UPDATED": "{{username}} has updated the attribute \"{{field_name}}\" of the epic {{obj_name}}",
"EPIC_UPDATED_WITH_NEW_VALUE": "{{username}} has updated the attribute \"{{field_name}}\" of the epic {{obj_name}} to {{new_value}}",
"EPIC_UPDATED_WITH_NEW_COLOR": "{{username}} has updated the \"{{field_name}}\" of the epic {{obj_name}} to <span class=\"new-color\" style=\"background: {{new_value}}\"></span>",
"NEW_COMMENT_US": "{{username}} comentou na História de Usuário {{obj_name}}", "NEW_COMMENT_US": "{{username}} comentou na História de Usuário {{obj_name}}",
"NEW_COMMENT_ISSUE": "{{username}} comentou no problema {{obj_name}}", "NEW_COMMENT_ISSUE": "{{username}} comentou no problema {{obj_name}}",
"NEW_COMMENT_TASK": "{{username}} comentou na tarefa {{obj_name}}", "NEW_COMMENT_TASK": "{{username}} comentou na tarefa {{obj_name}}",
"NEW_COMMENT_EPIC": "{{username}} has commented in the epic {{obj_name}}",
"NEW_MEMBER": "{{project_name}} tem um membro novo", "NEW_MEMBER": "{{project_name}} tem um membro novo",
"US_ADDED_MILESTONE": "{{username}} adicionou a História de Usuário {{obj_name}} a {{sprint_name}}", "US_ADDED_MILESTONE": "{{username}} adicionou a História de Usuário {{obj_name}} a {{sprint_name}}",
"US_MOVED": "{{username}} moveu a História de Usuário {{obj_name}}", "US_MOVED": "{{username}} moveu a História de Usuário {{obj_name}}",
@ -1499,7 +1637,7 @@
}, },
"STEP3": { "STEP3": {
"TITLE": "Observando", "TITLE": "Observando",
"TEXT1": "And right here you will find the ones in your projects that you want to know about.", "TEXT1": "E aqui você vai encontrar os do seu projeto que você escolheu seguir.",
"TEXT2": "Você já está trabalhando com Taiga ;)" "TEXT2": "Você já está trabalhando com Taiga ;)"
}, },
"STEP4": { "STEP4": {
@ -1555,7 +1693,7 @@
"VIEW_MORE": "Visualizar mais", "VIEW_MORE": "Visualizar mais",
"RECRUITING": "Este projeto esta procurando colaboradores", "RECRUITING": "Este projeto esta procurando colaboradores",
"FEATURED": "Featured Projects", "FEATURED": "Featured Projects",
"EMPTY": "There are no projects to show with this search criteria.<br> Try again!", "EMPTY": "Não há projetos para exibir sob esse critério de pesquisa.<br> Tente novamente!",
"FILTERS": { "FILTERS": {
"ALL": "Tudo", "ALL": "Tudo",
"KANBAN": "Kanban", "KANBAN": "Kanban",

View File

@ -35,19 +35,26 @@
"ONE_ITEM_LINE": "Один объект на строку...", "ONE_ITEM_LINE": "Один объект на строку...",
"NEW_BULK": "Добавить пакетно", "NEW_BULK": "Добавить пакетно",
"RELATED_TASKS": "Связанные задачи", "RELATED_TASKS": "Связанные задачи",
"PREVIOUS": "Предыдущий",
"NEXT": "Следующий",
"LOGOUT": "Выйти", "LOGOUT": "Выйти",
"EXTERNAL_USER": "внешний пользователь", "EXTERNAL_USER": "внешний пользователь",
"GENERIC_ERROR": "Один из Умпа-Лумп говорит {{error}}.", "GENERIC_ERROR": "Один из Умпа-Лумп говорит {{error}}.",
"IOCAINE_TEXT": "Чувствуете, что задание берет верх над вами? Дайте другим знать об этом, нажав на \"Иокаин\", когда редактируете задание. Возможно стать неуязвимым к этому (выдуманному) смертельном яду, потребляя небольшие количества время от времени, так же как возможно стать лучше в том, что вы делаете, временами беря на себя дополнительные препятствия!", "IOCAINE_TEXT": "Чувствуете, что задание берет верх над вами? Дайте другим знать об этом, нажав на \"Иокаин\", когда редактируете задание. Возможно стать неуязвимым к этому (выдуманному) смертельном яду, потребляя небольшие количества время от времени, так же как возможно стать лучше в том, что вы делаете, временами беря на себя дополнительные препятствия!",
"CLIENT_REQUIREMENT": "Client requirement is new requirement that was not previously expected and it is required to be part of the project", "CLIENT_REQUIREMENT": "Client requirement is new requirement that was not previously expected and it is required to be part of the project",
"TEAM_REQUIREMENT": "Team requirement is a requirement that must exist in the project but should have no cost for the client", "TEAM_REQUIREMENT": "Team requirement is a requirement that must exist in the project but should have no cost for the client",
"OWNER": "Project Owner", "OWNER": "Владелец проекта",
"CAPSLOCK_WARNING": "Be careful! You are using capital letters in an input field that is case sensitive.", "CAPSLOCK_WARNING": "Be careful! You are using capital letters in an input field that is case sensitive.",
"CONFIRM_CLOSE_EDIT_MODE_TITLE": "Are you sure you want to close the edit mode?", "CONFIRM_CLOSE_EDIT_MODE_TITLE": "Are you sure you want to close the edit mode?",
"CONFIRM_CLOSE_EDIT_MODE_MESSAGE": "Remember that if you close the edit mode without saving all the changes will be lost", "CONFIRM_CLOSE_EDIT_MODE_MESSAGE": "Remember that if you close the edit mode without saving all the changes will be lost",
"RELATED_USERSTORIES": "Related user stories",
"CARD": {
"ASSIGN_TO": "Assign To",
"EDIT": "Edit card"
},
"FORM_ERRORS": { "FORM_ERRORS": {
"DEFAULT_MESSAGE": "Кажется, это значение некорректно.", "DEFAULT_MESSAGE": "Кажется, это значение некорректно.",
"TYPE_EMAIL": "Это значение должно быть корректным email-адресом.", "TYPE_EMAIL": "Значение должно быть корректной электронной почтой.",
"TYPE_URL": "Это значение должно быть корректным URL-адресом.", "TYPE_URL": "Это значение должно быть корректным URL-адресом.",
"TYPE_URLSTRICT": "Это значение должно быть корректным URL-адресом.", "TYPE_URLSTRICT": "Это значение должно быть корректным URL-адресом.",
"TYPE_NUMBER": "Это значение должно быть правильным числом", "TYPE_NUMBER": "Это значение должно быть правильным числом",
@ -115,8 +122,9 @@
"USER_STORY": "Пользовательская история", "USER_STORY": "Пользовательская история",
"TASK": "Задача", "TASK": "Задача",
"ISSUE": "Запрос", "ISSUE": "Запрос",
"EPIC": "Epic",
"TAGS": { "TAGS": {
"PLACEHOLDER": "Назначьте тэг", "PLACEHOLDER": "Enter tag",
"DELETE": "Удалить тэг", "DELETE": "Удалить тэг",
"ADD": "Добавить тэг" "ADD": "Добавить тэг"
}, },
@ -193,12 +201,29 @@
"CONFIRM_DELETE": "Remeber that all values in this custom field will be deleted.\n Are you sure you want to continue?" "CONFIRM_DELETE": "Remeber that all values in this custom field will be deleted.\n Are you sure you want to continue?"
}, },
"FILTERS": { "FILTERS": {
"TITLE": "фильтры", "TITLE": "Фильтры",
"INPUT_PLACEHOLDER": "Название ссылки", "INPUT_PLACEHOLDER": "Название ссылки",
"TITLE_ACTION_FILTER_BUTTON": "поиск", "TITLE_ACTION_FILTER_BUTTON": "поиск",
"BREADCRUMB_TITLE": "назад к категориям", "INPUT_SEARCH_PLACEHOLDER": "Название ссылки",
"BREADCRUMB_FILTERS": "Фильтры", "TITLE_ACTION_SEARCH": "Поиск",
"BREADCRUMB_STATUS": "cтатус" "ACTION_SAVE_CUSTOM_FILTER": "сохранить как специальный фильтр",
"PLACEHOLDER_FILTER_NAME": "Введите название фильтра и нажмите \"ввод\"",
"APPLIED_FILTERS_NUM": "filters applied",
"CATEGORIES": {
"TYPE": "Тип",
"STATUS": "Статус",
"SEVERITY": "Важность",
"PRIORITIES": "Приоритеты",
"TAGS": "Тэги",
"ASSIGNED_TO": "Назначено",
"CREATED_BY": "Создано",
"CUSTOM_FILTERS": "Собственные фильтры",
"EPIC": "Epic"
},
"CONFIRM_DELETE": {
"TITLE": "Удалить фильтр",
"MESSAGE": "специальный фильтр '{{customFilterName}}'"
}
}, },
"WYSIWYG": { "WYSIWYG": {
"H1_BUTTON": "Заголовок первого уровня", "H1_BUTTON": "Заголовок первого уровня",
@ -228,9 +253,18 @@
"PREVIEW_BUTTON": "Предварительный просмотр", "PREVIEW_BUTTON": "Предварительный просмотр",
"EDIT_BUTTON": "Редактировать", "EDIT_BUTTON": "Редактировать",
"ATTACH_FILE_HELP": "Attach files by dragging & dropping on the textarea above.", "ATTACH_FILE_HELP": "Attach files by dragging & dropping on the textarea above.",
"ATTACH_FILE_HELP_SAVE_FIRST": "Save first before if you want to attach files by dragging & dropping on the textarea above.",
"MARKDOWN_HELP": "Помощь по синтаксису Markdown" "MARKDOWN_HELP": "Помощь по синтаксису Markdown"
}, },
"PERMISIONS_CATEGORIES": { "PERMISIONS_CATEGORIES": {
"EPICS": {
"NAME": "Epics",
"VIEW_EPICS": "View epics",
"ADD_EPICS": "Add epics",
"MODIFY_EPICS": "Modify epics",
"COMMENT_EPICS": "Comment epics",
"DELETE_EPICS": "Delete epics"
},
"SPRINTS": { "SPRINTS": {
"NAME": "Спринты", "NAME": "Спринты",
"VIEW_SPRINTS": "Посмотреть спринты", "VIEW_SPRINTS": "Посмотреть спринты",
@ -243,6 +277,7 @@
"VIEW_USER_STORIES": "Просматривать пользовательские истории", "VIEW_USER_STORIES": "Просматривать пользовательские истории",
"ADD_USER_STORIES": "Добавлять пользовательские истории", "ADD_USER_STORIES": "Добавлять пользовательские истории",
"MODIFY_USER_STORIES": "Изменять пользовательские истории", "MODIFY_USER_STORIES": "Изменять пользовательские истории",
"COMMENT_USER_STORIES": "Comment user stories",
"DELETE_USER_STORIES": "Удалять пользовательские истории" "DELETE_USER_STORIES": "Удалять пользовательские истории"
}, },
"TASKS": { "TASKS": {
@ -250,6 +285,7 @@
"VIEW_TASKS": "Просмотреть задачи", "VIEW_TASKS": "Просмотреть задачи",
"ADD_TASKS": "Добавить задачи", "ADD_TASKS": "Добавить задачи",
"MODIFY_TASKS": "Редактировать задачи", "MODIFY_TASKS": "Редактировать задачи",
"COMMENT_TASKS": "Comment tasks",
"DELETE_TASKS": "Удалить задачи" "DELETE_TASKS": "Удалить задачи"
}, },
"ISSUES": { "ISSUES": {
@ -257,6 +293,7 @@
"VIEW_ISSUES": "Посмотреть запросы", "VIEW_ISSUES": "Посмотреть запросы",
"ADD_ISSUES": "Добавить запросы", "ADD_ISSUES": "Добавить запросы",
"MODIFY_ISSUES": "Изменить запросы", "MODIFY_ISSUES": "Изменить запросы",
"COMMENT_ISSUES": "Comment issues",
"DELETE_ISSUES": "Удалить запросы" "DELETE_ISSUES": "Удалить запросы"
}, },
"WIKI": { "WIKI": {
@ -287,7 +324,7 @@
}, },
"LOGIN_COMMON": { "LOGIN_COMMON": {
"HEADER": "У меня уже есть логин в Taiga", "HEADER": "У меня уже есть логин в Taiga",
"PLACEHOLDER_AUTH_NAME": "Логин или email (с учетом регистра)", "PLACEHOLDER_AUTH_NAME": "Имя пользователя или электронная почта (с учётом регистра)",
"LINK_FORGOT_PASSWORD": "Забыли?", "LINK_FORGOT_PASSWORD": "Забыли?",
"TITLE_LINK_FORGOT_PASSWORD": "Вы забыли свой пароль?", "TITLE_LINK_FORGOT_PASSWORD": "Вы забыли свой пароль?",
"ACTION_ENTER": "Ввод", "ACTION_ENTER": "Ввод",
@ -295,7 +332,7 @@
"PLACEHOLDER_AUTH_PASSWORD": "Пароль (чувствителен к регистру)" "PLACEHOLDER_AUTH_PASSWORD": "Пароль (чувствителен к регистру)"
}, },
"LOGIN_FORM": { "LOGIN_FORM": {
"ERROR_AUTH_INCORRECT": "Oompa Loompas считает, что Ваш логин, email или пароль неправильный.", "ERROR_AUTH_INCORRECT": "Oompa Loompas считает, что ваше имя пользователя, электронная почта или пароль неправильные.",
"SUCCESS": "Oompa Loompas счастлив, добро пожаловать в Тайгу!" "SUCCESS": "Oompa Loompas счастлив, добро пожаловать в Тайгу!"
}, },
"REGISTER": { "REGISTER": {
@ -306,7 +343,7 @@
"TITLE": "Зарегистрируйте аккаунт Taiga (бесплатно)", "TITLE": "Зарегистрируйте аккаунт Taiga (бесплатно)",
"PLACEHOLDER_NAME": "Выберите имя учётной записи (с учётом регистра)", "PLACEHOLDER_NAME": "Выберите имя учётной записи (с учётом регистра)",
"PLACEHOLDER_FULL_NAME": "Введите Ваше полное имя", "PLACEHOLDER_FULL_NAME": "Введите Ваше полное имя",
"PLACEHOLDER_EMAIL": "Ваш email", "PLACEHOLDER_EMAIL": "Ваша электронная почта",
"PLACEHOLDER_PASSWORD": "Задайте новый пароль (с учетом регистра)", "PLACEHOLDER_PASSWORD": "Задайте новый пароль (с учетом регистра)",
"ACTION_SIGN_UP": "Зарегистрироваться", "ACTION_SIGN_UP": "Зарегистрироваться",
"TITLE_LINK_LOGIN": "Войти", "TITLE_LINK_LOGIN": "Войти",
@ -318,12 +355,12 @@
}, },
"FORGOT_PASSWORD_FORM": { "FORGOT_PASSWORD_FORM": {
"TITLE": "Упс, забыли пароль?", "TITLE": "Упс, забыли пароль?",
"SUBTITLE": "Введите Ваш логин или email для получения нового пароля", "SUBTITLE": "Введите ваше имя пользователя или электронную почту, чтобы получить новый пароль",
"PLACEHOLDER_FIELD": "Логин или e-mail", "PLACEHOLDER_FIELD": "Имя пользователя или электронная почта",
"ACTION_RESET_PASSWORD": "Сбросить пароль", "ACTION_RESET_PASSWORD": "Сбросить пароль",
"LINK_CANCEL": "Не, давай назад, думаю я вспомню.", "LINK_CANCEL": "Не, давай назад, думаю я вспомню.",
"SUCCESS_TITLE": "Check your inbox!", "SUCCESS_TITLE": "Проверьте Вашу почту!",
"SUCCESS_TEXT": "We sent you an email with the instructions to set a new password", "SUCCESS_TEXT": "Мы отправили вам письмо с инструкциями по восстановлению пароля",
"ERROR": "Умпа-Лумпы говорят, что вы еще не зарегистрированы." "ERROR": "Умпа-Лумпы говорят, что вы еще не зарегистрированы."
}, },
"CHANGE_PASSWORD": { "CHANGE_PASSWORD": {
@ -359,13 +396,48 @@
"HOME": { "HOME": {
"PAGE_TITLE": "Домашняя страница - Taiga", "PAGE_TITLE": "Домашняя страница - Taiga",
"PAGE_DESCRIPTION": "Главная страница Taiga с вашими основными проектами, назначенными и отслеживаемыми ПИ, задачами и запросами", "PAGE_DESCRIPTION": "Главная страница Taiga с вашими основными проектами, назначенными и отслеживаемыми ПИ, задачами и запросами",
"EMPTY_WORKING_ON": "<strong>It feels empty, doesn't it?</strong> Start working with Taiga and you'll see here the stories, tasks and issues you are working on.", "EMPTY_WORKING_ON": "<strong>Тут кажется пусто, не правда ли?</strong> Начинайте использовать Taiga и вы увидите здесь истории, задачи и запросы над которыми вы сейчас работаете.",
"EMPTY_WATCHING": "<strong>Следите</strong> за пользовательскими историями, задачами, запросами в ваших проектах и будьте уведомлены об изменениях :)", "EMPTY_WATCHING": "<strong>Следите</strong> за пользовательскими историями, задачами, запросами в ваших проектах и будьте уведомлены об изменениях :)",
"EMPTY_PROJECT_LIST": "У Вас пока нет проектов", "EMPTY_PROJECT_LIST": "У Вас пока нет проектов",
"WORKING_ON_SECTION": "Работает над", "WORKING_ON_SECTION": "Работает над",
"WATCHING_SECTION": "Отслеживаемые", "WATCHING_SECTION": "Отслеживаемые",
"DASHBOARD": "Рабочий стол с проектами" "DASHBOARD": "Рабочий стол с проектами"
}, },
"EPICS": {
"TITLE": "EPICS",
"SECTION_NAME": "Epics",
"EPIC": "EPIC",
"PAGE_TITLE": "Epics - {{projectName}}",
"PAGE_DESCRIPTION": "The epics list of the project {{projectName}}: {{projectDescription}}",
"DASHBOARD": {
"ADD": "+ ADD EPIC",
"UNASSIGNED": "Не назначено"
},
"EMPTY": {
"TITLE": "It looks like there aren't any epics yet",
"EXPLANATION": "Epics are items at a higher level that encompass user stories.<br />Epics are at the top of the hierarchy and can be used to group user stories together.",
"HELP": "Learn more about epics"
},
"TABLE": {
"VOTES": "Голоса",
"NAME": "Имя",
"PROJECT": "Проект",
"SPRINT": "Спринт",
"ASSIGNED_TO": "Assigned",
"STATUS": "Статус",
"PROGRESS": "Progress",
"VIEW_OPTIONS": "View options"
},
"CREATE": {
"TITLE": "New Epic",
"PLACEHOLDER_DESCRIPTION": "Please add descriptive text to help others better understand this epic",
"TEAM_REQUIREMENT": "Team requirement",
"CLIENT_REQUIREMENT": "Client requirement",
"BLOCKED": "Заблокирован",
"BLOCKED_NOTE_PLACEHOLDER": "Why is this epic blocked?",
"CREATE_EPIC": "Create epic"
}
},
"PROJECTS": { "PROJECTS": {
"PAGE_TITLE": "Мои проекты", "PAGE_TITLE": "Мои проекты",
"PAGE_DESCRIPTION": "Список Ваших проектов, отсортируйте их или создайте новый.", "PAGE_DESCRIPTION": "Список Ваших проектов, отсортируйте их или создайте новый.",
@ -402,7 +474,8 @@
"ADMIN": { "ADMIN": {
"COMMON": { "COMMON": {
"TITLE_ACTION_EDIT_VALUE": "Изменить значение", "TITLE_ACTION_EDIT_VALUE": "Изменить значение",
"TITLE_ACTION_DELETE_VALUE": "Удалить значение" "TITLE_ACTION_DELETE_VALUE": "Удалить значение",
"TITLE_ACTION_DELETE_TAG": "Удалить тэг"
}, },
"HELP": "Вам нужна помощь? Проверьте нашу страницу техподдержки!", "HELP": "Вам нужна помощь? Проверьте нашу страницу техподдержки!",
"PROJECT_DEFAULT_VALUES": { "PROJECT_DEFAULT_VALUES": {
@ -425,7 +498,7 @@
"LOADING_TITLE": "Мы создали ваш файл резервной копии", "LOADING_TITLE": "Мы создали ваш файл резервной копии",
"DUMP_READY": "Файл резервной копии готов!", "DUMP_READY": "Файл резервной копии готов!",
"LOADING_MESSAGE": "Пожалуйста, не закрывайте эту страницу", "LOADING_MESSAGE": "Пожалуйста, не закрывайте эту страницу",
"ASYNC_MESSAGE": "Мы отправим вам email когда будет готово.", "ASYNC_MESSAGE": "Мы отправим вам письмо когда будет готово.",
"SYNC_MESSAGE": "Если загрузка не начинается самостоятельно, нажмите <a href='{{url}}' download title='Download the dump file'>здесь</a>.", "SYNC_MESSAGE": "Если загрузка не начинается самостоятельно, нажмите <a href='{{url}}' download title='Download the dump file'>здесь</a>.",
"ERROR": "У Oompa Loompas возникли проблемы при создании резервной копии. Повторите еще раз.", "ERROR": "У Oompa Loompas возникли проблемы при создании резервной копии. Повторите еще раз.",
"ERROR_BUSY": "Извините, Oompa Loompas очень загружен сейчас. Повторите через несколько минут.", "ERROR_BUSY": "Извините, Oompa Loompas очень загружен сейчас. Повторите через несколько минут.",
@ -435,9 +508,11 @@
"TITLE": "Модули", "TITLE": "Модули",
"ENABLE": "Включить", "ENABLE": "Включить",
"DISABLE": "Выключить", "DISABLE": "Выключить",
"EPICS": "Epics",
"EPICS_DESCRIPTION": "Visualize and manage the most strategic part of your project",
"BACKLOG": "Список задач", "BACKLOG": "Список задач",
"BACKLOG_DESCRIPTION": "Управляйте пользовательскими историями, чтобы поддерживать организованное видение важных и приоритетных задач.", "BACKLOG_DESCRIPTION": "Управляйте пользовательскими историями, чтобы поддерживать организованное видение важных и приоритетных задач.",
"NUMBER_SPRINTS": "Expected number of sprints", "NUMBER_SPRINTS": "Ожидаемое количество спринтов",
"NUMBER_SPRINTS_HELP": "0 for an undetermined number", "NUMBER_SPRINTS_HELP": "0 for an undetermined number",
"NUMBER_US_POINTS": "Expected total of story points", "NUMBER_US_POINTS": "Expected total of story points",
"NUMBER_US_POINTS_HELP": "0 for an undetermined number", "NUMBER_US_POINTS_HELP": "0 for an undetermined number",
@ -448,9 +523,9 @@
"WIKI": "Вики", "WIKI": "Вики",
"WIKI_DESCRIPTION": "Добавляйте, изменяйте или удаляйте контент совместно с остальными. Это самое правильное место для документации вашего проекта.", "WIKI_DESCRIPTION": "Добавляйте, изменяйте или удаляйте контент совместно с остальными. Это самое правильное место для документации вашего проекта.",
"MEETUP": "Созвониться", "MEETUP": "Созвониться",
"MEETUP_DESCRIPTION": "Choose your videoconference system.", "MEETUP_DESCRIPTION": "Выберите Вашу систему видеоконференций",
"SELECT_VIDEOCONFERENCE": "Выберите систему видеоконференций", "SELECT_VIDEOCONFERENCE": "Выберите систему видеоконференций",
"SALT_CHAT_ROOM": "Add a prefix to the chatroom name", "SALT_CHAT_ROOM": "Добавить префикс к имени чата",
"JITSI_CHAT_ROOM": "Jitsi", "JITSI_CHAT_ROOM": "Jitsi",
"APPEARIN_CHAT_ROOM": "AppearIn", "APPEARIN_CHAT_ROOM": "AppearIn",
"TALKY_CHAT_ROOM": "Talky", "TALKY_CHAT_ROOM": "Talky",
@ -472,20 +547,20 @@
"PRIVATE_OR_PUBLIC": "В чём разница между публичными и приватными проектами?", "PRIVATE_OR_PUBLIC": "В чём разница между публичными и приватными проектами?",
"DELETE": "Удалить проект", "DELETE": "Удалить проект",
"LOGO_HELP": "Изображение будет отмасштабировано до 80x80px.", "LOGO_HELP": "Изображение будет отмасштабировано до 80x80px.",
"CHANGE_LOGO": "Change logo", "CHANGE_LOGO": "Изменить лого",
"ACTION_USE_DEFAULT_LOGO": "Использовать картинку по умолчанию", "ACTION_USE_DEFAULT_LOGO": "Использовать картинку по умолчанию",
"MAX_PRIVATE_PROJECTS": "You've reached the maximum number of private projects allowed by your current plan", "MAX_PRIVATE_PROJECTS": "Вы достигли максимального числа приватных проектов которое разрешено вашим планом.",
"MAX_PRIVATE_PROJECTS_MEMBERS": "The maximum number of members for private projects has been exceeded", "MAX_PRIVATE_PROJECTS_MEMBERS": "Максимальное количество участников в приватном проекте достигло лимита",
"MAX_PUBLIC_PROJECTS": "Unfortunately, you've reached the maximum number of public projects allowed by your current plan", "MAX_PUBLIC_PROJECTS": "Unfortunately, you've reached the maximum number of public projects allowed by your current plan",
"MAX_PUBLIC_PROJECTS_MEMBERS": "The project exceeds your maximum number of members for public projects", "MAX_PUBLIC_PROJECTS_MEMBERS": "The project exceeds your maximum number of members for public projects",
"PROJECT_OWNER": "Project owner", "PROJECT_OWNER": "Владелец проекта",
"REQUEST_OWNERSHIP": "Request ownership", "REQUEST_OWNERSHIP": "Запрос владельца",
"REQUEST_OWNERSHIP_CONFIRMATION_TITLE": "Do you want to become the new project owner?", "REQUEST_OWNERSHIP_CONFIRMATION_TITLE": "Хотите стать новым владельцем проекта?",
"REQUEST_OWNERSHIP_DESC": "Request that current project owner {{name}} transfer ownership of this project to you.", "REQUEST_OWNERSHIP_DESC": "Request that current project owner {{name}} transfer ownership of this project to you.",
"REQUEST_OWNERSHIP_BUTTON": "Запрос", "REQUEST_OWNERSHIP_BUTTON": "Запрос",
"REQUEST_OWNERSHIP_SUCCESS": "We'll notify the project owner", "REQUEST_OWNERSHIP_SUCCESS": "Мы уведомим владельца проекта",
"CHANGE_OWNER": "Change owner", "CHANGE_OWNER": "Сменить владельца",
"CHANGE_OWNER_SUCCESS_TITLE": "Ok, your request has been sent!", "CHANGE_OWNER_SUCCESS_TITLE": "ОК, ваш запрос был отправлен!",
"CHANGE_OWNER_SUCCESS_DESC": "We will notify you by email if the project ownership request is accepted or declined" "CHANGE_OWNER_SUCCESS_DESC": "We will notify you by email if the project ownership request is accepted or declined"
}, },
"REPORTS": { "REPORTS": {
@ -497,18 +572,21 @@
"REGENERATE_SUBTITLE": "Вы собираетесь изменить ссылку доступа к данным CSV. Прежний вариант ссылки перестанет работать. Вы уверены?" "REGENERATE_SUBTITLE": "Вы собираетесь изменить ссылку доступа к данным CSV. Прежний вариант ссылки перестанет работать. Вы уверены?"
}, },
"CSV": { "CSV": {
"SECTION_TITLE_EPIC": "epics reports",
"SECTION_TITLE_US": "Отчёты по пользовательским историям", "SECTION_TITLE_US": "Отчёты по пользовательским историям",
"SECTION_TITLE_TASK": "отчёты о задачах", "SECTION_TITLE_TASK": "отчёты о задачах",
"SECTION_TITLE_ISSUE": "отчёты о запросах", "SECTION_TITLE_ISSUE": "отчёты о запросах",
"DOWNLOAD": "Скачать CSV", "DOWNLOAD": "Скачать CSV",
"URL_FIELD_PLACEHOLDER": "Упс, забыли пароль?", "URL_FIELD_PLACEHOLDER": "Упс, забыли пароль?",
"TITLE_REGENERATE_URL": " Сделать CSV ссылку ещё раз", "TITLE_REGENERATE_URL": "Сделать CSV ссылку ещё раз",
"ACTION_GENERATE_URL": "Сгенерировать ссылку", "ACTION_GENERATE_URL": "Сгенерировать ссылку",
"ACTION_REGENERATE": "Создать заново" "ACTION_REGENERATE": "Создать заново"
}, },
"CUSTOM_FIELDS": { "CUSTOM_FIELDS": {
"TITLE": "Пользовательские поля", "TITLE": "Пользовательские поля",
"SUBTITLE": "Укажите специальные поля для ваших пользовательских историй, задач и запросов", "SUBTITLE": "Укажите специальные поля для ваших пользовательских историй, задач и запросов",
"EPIC_DESCRIPTION": "Epics custom fields",
"EPIC_ADD": "Add a custom field in epics",
"US_DESCRIPTION": "Специальные поля для пользовательских историй", "US_DESCRIPTION": "Специальные поля для пользовательских историй",
"US_ADD": "Добавить специальное поле для пользовательских историй", "US_ADD": "Добавить специальное поле для пользовательских историй",
"TASK_DESCRIPTION": "Специальные поля задач", "TASK_DESCRIPTION": "Специальные поля задач",
@ -546,7 +624,8 @@
"PROJECT_VALUES_STATUS": { "PROJECT_VALUES_STATUS": {
"TITLE": "Статус", "TITLE": "Статус",
"SUBTITLE": "Укажите, какие статусы будут принимать ваши пользовательские истории, задачи и запросы", "SUBTITLE": "Укажите, какие статусы будут принимать ваши пользовательские истории, задачи и запросы",
"US_TITLE": "Статусы ПИ", "EPIC_TITLE": "Epic Statuses",
"US_TITLE": "User Story Statuses",
"TASK_TITLE": "Статус задач", "TASK_TITLE": "Статус задач",
"ISSUE_TITLE": "Статусы запроса" "ISSUE_TITLE": "Статусы запроса"
}, },
@ -556,6 +635,17 @@
"ISSUE_TITLE": "Типы запросов", "ISSUE_TITLE": "Типы запросов",
"ACTION_ADD": "Добавить новый" "ACTION_ADD": "Добавить новый"
}, },
"PROJECT_VALUES_TAGS": {
"TITLE": "Тэги",
"SUBTITLE": "Просмотреть и изменить цвет ваших тэгов",
"EMPTY": "В данный момент тэги отсутствуют",
"EMPTY_SEARCH": "It looks like nothing was found with your search criteria",
"ACTION_ADD": "Добавить тэг",
"NEW_TAG": "Новый тэг",
"MIXING_HELP_TEXT": "Выберите тэги которые вы хотели бы объединить",
"MIXING_MERGE": "Объединить Тэги",
"SELECTED": "Выбранные"
},
"ROLES": { "ROLES": {
"PAGE_TITLE": "Роли - {{projectName}}", "PAGE_TITLE": "Роли - {{projectName}}",
"WARNING_NO_ROLE": "Осторожнее: ни с какими ролями на вашем проекте участники не смогут оценить очки для пользовательских историй.", "WARNING_NO_ROLE": "Осторожнее: ни с какими ролями на вашем проекте участники не смогут оценить очки для пользовательских историй.",
@ -588,6 +678,10 @@
"SECTION_NAME": "Github", "SECTION_NAME": "Github",
"PAGE_TITLE": "Github - {{projectName}}" "PAGE_TITLE": "Github - {{projectName}}"
}, },
"GOGS": {
"SECTION_NAME": "Gogs",
"PAGE_TITLE": "Gogs - {{projectName}}"
},
"WEBHOOKS": { "WEBHOOKS": {
"PAGE_TITLE": "Веб-хуки - {{projectName}}", "PAGE_TITLE": "Веб-хуки - {{projectName}}",
"SECTION_NAME": "Веб-хуки", "SECTION_NAME": "Веб-хуки",
@ -643,13 +737,14 @@
"DEFAULT_DELETE_MESSAGE": "приглашение на {{email}}" "DEFAULT_DELETE_MESSAGE": "приглашение на {{email}}"
}, },
"DEFAULT_VALUES": { "DEFAULT_VALUES": {
"LABEL_EPIC_STATUS": "Default value for epic status selector",
"LABEL_US_STATUS": "Default value for user story status selector",
"LABEL_POINTS": "Значения по умолчанию для выбора очков", "LABEL_POINTS": "Значения по умолчанию для выбора очков",
"LABEL_US": "Значение по умолчанию для статуса ПИ",
"LABEL_TASK_STATUS": "Значение по умолчанию для статуса задачи", "LABEL_TASK_STATUS": "Значение по умолчанию для статуса задачи",
"LABEL_PRIORITY": "Значение по умолчанию для выбора приоритета",
"LABEL_SEVERITY": "Значение важности по умолчанию",
"LABEL_ISSUE_TYPE": "Значение по умолчанию для типа запроса", "LABEL_ISSUE_TYPE": "Значение по умолчанию для типа запроса",
"LABEL_ISSUE_STATUS": "Значение по умолчанию для статуса запроса" "LABEL_ISSUE_STATUS": "Значение по умолчанию для статуса запроса",
"LABEL_PRIORITY": "Значение по умолчанию для выбора приоритета",
"LABEL_SEVERITY": "Значение важности по умолчанию"
}, },
"STATUS": { "STATUS": {
"PLACEHOLDER_WRITE_STATUS_NAME": "Укажите название для нового статуса" "PLACEHOLDER_WRITE_STATUS_NAME": "Укажите название для нового статуса"
@ -681,7 +776,8 @@
"PRIORITIES": "Приоритет", "PRIORITIES": "Приоритет",
"SEVERITIES": "Степени важности", "SEVERITIES": "Степени важности",
"TYPES": "Типы", "TYPES": "Типы",
"CUSTOM_FIELDS": "Собственные поля" "CUSTOM_FIELDS": "Собственные поля",
"TAGS": "Тэги"
}, },
"SUBMENU_PROJECT_PROFILE": { "SUBMENU_PROJECT_PROFILE": {
"TITLE": "Профиль проекта" "TITLE": "Профиль проекта"
@ -697,8 +793,8 @@
"PROJECT_TRANSFER": { "PROJECT_TRANSFER": {
"DO_YOU_ACCEPT_PROJECT_OWNERNSHIP": "Would you like to become the new project owner?", "DO_YOU_ACCEPT_PROJECT_OWNERNSHIP": "Would you like to become the new project owner?",
"PRIVATE": "Private", "PRIVATE": "Private",
"ACCEPTED_PROJECT_OWNERNSHIP": "Congratulations! You're now the new project owner.", "ACCEPTED_PROJECT_OWNERNSHIP": "Поздравляем! Вы новый владелец проекта.",
"REJECTED_PROJECT_OWNERNSHIP": "OK. We'll contact the current project owner", "REJECTED_PROJECT_OWNERNSHIP": "Хорошо. Мы свяжемся с текущим владельцем проекта",
"ACCEPT": "Принимаю", "ACCEPT": "Принимаю",
"REJECT": "Reject", "REJECT": "Reject",
"PROPOSE_OWNERSHIP": "<strong>{{owner}}</strong>, the current owner of the project <strong>{{project}}</strong> has asked that you become the new project owner.", "PROPOSE_OWNERSHIP": "<strong>{{owner}}</strong>, the current owner of the project <strong>{{project}}</strong> has asked that you become the new project owner.",
@ -751,6 +847,8 @@
"FILTER_TYPE_ALL_TITLE": "Показать все", "FILTER_TYPE_ALL_TITLE": "Показать все",
"FILTER_TYPE_PROJECTS": "Проекты", "FILTER_TYPE_PROJECTS": "Проекты",
"FILTER_TYPE_PROJECT_TITLES": "Показать только проекты", "FILTER_TYPE_PROJECT_TITLES": "Показать только проекты",
"FILTER_TYPE_EPICS": "Epics",
"FILTER_TYPE_EPIC_TITLES": "Show only epics",
"FILTER_TYPE_USER_STORIES": "Истории", "FILTER_TYPE_USER_STORIES": "Истории",
"FILTER_TYPE_USER_STORIES_TITLES": "Показывать только пользовательские истории", "FILTER_TYPE_USER_STORIES_TITLES": "Показывать только пользовательские истории",
"FILTER_TYPE_TASKS": "Задачи", "FILTER_TYPE_TASKS": "Задачи",
@ -771,8 +869,8 @@
"WATCHERS_COUNTER_TITLE": "{total, plural, one{один наблюдатель} other{# наблюдателя (-ей)}}", "WATCHERS_COUNTER_TITLE": "{total, plural, one{один наблюдатель} other{# наблюдателя (-ей)}}",
"MEMBERS_COUNTER_TITLE": "{total, plural, one{one member} other{# members}}", "MEMBERS_COUNTER_TITLE": "{total, plural, one{one member} other{# members}}",
"BLOCKED_PROJECT": { "BLOCKED_PROJECT": {
"BLOCKED": "Blocked project", "BLOCKED": "Заблокированный проект",
"THIS_PROJECT_IS_BLOCKED": "This project is temporarily blocked", "THIS_PROJECT_IS_BLOCKED": "Этот проект временно заблокирован",
"TO_UNBLOCK_CONTACT_THE_ADMIN_STAFF": "In order to unblock your projects, contact the administrator." "TO_UNBLOCK_CONTACT_THE_ADMIN_STAFF": "In order to unblock your projects, contact the administrator."
}, },
"STATS": { "STATS": {
@ -890,8 +988,8 @@
"SECTION_NAME": "Удалить аккаунт", "SECTION_NAME": "Удалить аккаунт",
"CONFIRM": "Вы уверены, что хотите удалить ваш аккаунт?", "CONFIRM": "Вы уверены, что хотите удалить ваш аккаунт?",
"NEWSLETTER_LABEL_TEXT": "Я больше не хочу получать вашу новостную рассылку", "NEWSLETTER_LABEL_TEXT": "Я больше не хочу получать вашу новостную рассылку",
"CANCEL": "Back to settings", "CANCEL": "Вернуться к настройкам",
"ACCEPT": "Delete account", "ACCEPT": "Удалить аккаунт",
"BLOCK_PROJECT": "Note that all the projects you own projects will be <strong>blocked</strong> after you delete your account. If you do want a project blocked, transfer ownership to another member of each project prior to deleting your account.", "BLOCK_PROJECT": "Note that all the projects you own projects will be <strong>blocked</strong> after you delete your account. If you do want a project blocked, transfer ownership to another member of each project prior to deleting your account.",
"SUBTITLE": "Sorry to see you go. We'll be here if you should ever consider us again! :(" "SUBTITLE": "Sorry to see you go. We'll be here if you should ever consider us again! :("
}, },
@ -949,31 +1047,51 @@
}, },
"CREATE_MEMBER": { "CREATE_MEMBER": {
"PLACEHOLDER_INVITATION_TEXT": "(Необязательно) Добавьте персональный текст в приглашение. Скажите что-нибудь приятное вашим новым участникам ;-)", "PLACEHOLDER_INVITATION_TEXT": "(Необязательно) Добавьте персональный текст в приглашение. Скажите что-нибудь приятное вашим новым участникам ;-)",
"PLACEHOLDER_TYPE_EMAIL": "Укажите e-mail", "PLACEHOLDER_TYPE_EMAIL": "Введите электронную почту",
"LIMIT_USERS_WARNING_MESSAGE_FOR_OWNER": "Unfortunately, this project can't have more than <strong>{{maxMembers}}</strong> members.<br> If you would like to increase the current limit, please contact the administrator.", "LIMIT_USERS_WARNING_MESSAGE_FOR_OWNER": "You are about to reach the maximum number of members allowed for this project, <strong>{{maxMembers}}</strong> members. If you would like to increase the current limit, please contact the administrator.",
"LIMIT_USERS_WARNING_MESSAGE": "Unfortunately, this project can't have more than <strong>{{maxMembers}}</strong> members." "LIMIT_USERS_WARNING_MESSAGE": "You are about to reach the maximum number of members allowed for this project, <strong>{{maxMembers}}</strong> members."
}, },
"LEAVE_PROJECT_WARNING": { "LEAVE_PROJECT_WARNING": {
"TITLE": "Unfortunately, this project can't be left without an owner", "TITLE": "Unfortunately, this project can't be left without an owner",
"CURRENT_USER_OWNER": { "CURRENT_USER_OWNER": {
"DESC": "You are the current owner of this project. Before leaving, please transfer ownership to someone else.", "DESC": "You are the current owner of this project. Before leaving, please transfer ownership to someone else.",
"BUTTON": "Change the project owner" "BUTTON": "Сменить владельца проекта"
}, },
"OTHER_USER_OWNER": { "OTHER_USER_OWNER": {
"DESC": "Unfortunately, you can't delete a member who is also the current project owner. First, please assign a new project owner.", "DESC": "Unfortunately, you can't delete a member who is also the current project owner. First, please assign a new project owner.",
"BUTTON": "Request project owner change" "BUTTON": "Запрос смены владельца проекта"
} }
}, },
"CHANGE_OWNER": { "CHANGE_OWNER": {
"TITLE": "Who do you want to be the new project owner?", "TITLE": "Кого вы хотите назначить новым владельцем проекта?",
"ADD_COMMENT": "Add comment", "ADD_COMMENT": "Добавить комментарий",
"BUTTON": "Ask this project member to become the new project owner" "BUTTON": "Предложить участнику проекта стать его новым владельцем"
} }
}, },
"EPIC": {
"PAGE_TITLE": "{{epicSubject}} - Epic {{epicRef}} - {{projectName}}",
"PAGE_DESCRIPTION": "Status: {{epicStatus }}. Description: {{epicDescription}}",
"SECTION_NAME": "Epic",
"TITLE_LIGHTBOX_UNLINK_RELATED_USERSTORY": "Unlink related userstory",
"MSG_LIGHTBOX_UNLINK_RELATED_USERSTORY": "It will delete the link to the related userstory '{{subject}}'",
"ERROR_UNLINK_RELATED_USERSTORY": "We have not been able to unlink: {{errorMessage}}",
"CREATE_RELATED_USERSTORIES": "Create a relationship with",
"NEW_USERSTORY": "Новая пользовательская история",
"EXISTING_USERSTORY": "Existing user story",
"CHOOSE_PROJECT_FOR_CREATION": "What's the project?",
"SUBJECT": "Тема",
"SUBJECT_BULK_MODE": "Subject (bulk insert)",
"CHOOSE_PROJECT_FROM": "What's the project?",
"CHOOSE_USERSTORY": "What's the user story?",
"NO_USERSTORIES": "This project has no User Stories yet. Please select another project.",
"FILTER_USERSTORIES": "Filter user stories",
"LIGHTBOX_TITLE_BLOKING_EPIC": "Blocking epic",
"ACTION_DELETE": "Delete epic"
},
"US": { "US": {
"PAGE_TITLE": "{{userStorySubject}} - Пользовательская История {{userStoryRef}} - {{projectName}}", "PAGE_TITLE": "{{userStorySubject}} - Пользовательская История {{userStoryRef}} - {{projectName}}",
"PAGE_DESCRIPTION": "Статус: {{userStoryStatus }}. Выполнено {{userStoryProgressPercentage}}% ({{userStoryClosedTasks}} из {{userStoryTotalTasks}} задач). Очки: {{userStoryPoints}}. Описание: {{userStoryDescription}}", "PAGE_DESCRIPTION": "Статус: {{userStoryStatus }}. Выполнено {{userStoryProgressPercentage}}% ({{userStoryClosedTasks}} из {{userStoryTotalTasks}} задач). Очки: {{userStoryPoints}}. Описание: {{userStoryDescription}}",
"SECTION_NAME": "Детали пользовательских историй", "SECTION_NAME": "Пользовательская история",
"LINK_TASKBOARD": "Панель задач", "LINK_TASKBOARD": "Панель задач",
"TITLE_LINK_TASKBOARD": "Перейти к панели задач", "TITLE_LINK_TASKBOARD": "Перейти к панели задач",
"TOTAL_POINTS": "общее число очков", "TOTAL_POINTS": "общее число очков",
@ -983,15 +1101,24 @@
"TITLE_LINK_GO_TO_ISSUE": "Перейти к запросу", "TITLE_LINK_GO_TO_ISSUE": "Перейти к запросу",
"EXTERNAL_REFERENCE": "Эта ПИ была создана из:", "EXTERNAL_REFERENCE": "Эта ПИ была создана из:",
"GO_TO_EXTERNAL_REFERENCE": "Перейти в начало", "GO_TO_EXTERNAL_REFERENCE": "Перейти в начало",
"BLOCKED": "Эта пользовательская история заблокирована ", "BLOCKED": "Эта пользовательская история заблокирована",
"PREVIOUS": "предыдущая пользовательская история",
"NEXT": "следующая пользовательская история",
"TITLE_DELETE_ACTION": "Удалить пользовательскую историю", "TITLE_DELETE_ACTION": "Удалить пользовательскую историю",
"LIGHTBOX_TITLE_BLOKING_US": "Блокирующая ПИ", "LIGHTBOX_TITLE_BLOKING_US": "Блокирующая ПИ",
"TASK_COMPLETED": "{{totalClosedTasks}}/{{totalTasks}} задач выполнено", "TASK_COMPLETED": "{{totalClosedTasks}}/{{totalTasks}} задач выполнено",
"ASSIGN": "Поручить пользовательскую историю", "ASSIGN": "Поручить пользовательскую историю",
"NOT_ESTIMATED": "Не оценено", "NOT_ESTIMATED": "Не оценено",
"TOTAL_US_POINTS": "Всего очков за ПИ", "TOTAL_US_POINTS": "Всего очков за ПИ",
"TRIBE": {
"PUBLISH": "Publish as Gig in Taiga Tribe",
"PUBLISH_INFO": "Больше инфо",
"PUBLISH_TITLE": "More info on publishing in Taiga Tribe",
"PUBLISHED_AS_GIG": "Story published as Gig in Taiga Tribe",
"EDIT_LINK": "Редактировать ссылку",
"CLOSE": "Закрыть",
"SYNCHRONIZE_LINK": "synchronize with Taiga Tribe",
"PUBLISH_MORE_INFO_TITLE": "Do you need somebody for this task?",
"PUBLISH_MORE_INFO_TEXT": "<p>If you need help with a particular piece of work you can easily create gigs on<a href='taigatribe.com' title='Taiga Tribe'> Taiga Tribe </a> and receive help from all over the world. You will be able to control and manage the gig enjoying a great community eager to contribute.</p><p><a href='taigatribe.com' title='Taiga Tribe'> TaigaTribe </a> was born as a Taiga sibling. Both platforms can live separately but we believe that there is much power in using them combined so we are making sure the integration works like a charm.</p>"
},
"FIELDS": { "FIELDS": {
"TEAM_REQUIREMENT": "Требование от Команды", "TEAM_REQUIREMENT": "Требование от Команды",
"CLIENT_REQUIREMENT": "Требование клиента", "CLIENT_REQUIREMENT": "Требование клиента",
@ -999,28 +1126,47 @@
} }
}, },
"COMMENTS": { "COMMENTS": {
"DELETED_INFO": "Комментарий удален {{user}} {{date}}", "DELETED_INFO": "Комментарий удалён {{user}}",
"TITLE": "Комментарии", "TITLE": "Комментарии",
"COMMENTS_COUNT": "{{comments}} Comments",
"ORDER": "Порядок",
"OLDER_FIRST": "Сначала старые",
"RECENT_FIRST": "Сначала новые",
"COMMENT": "Комментарий", "COMMENT": "Комментарий",
"EDIT_COMMENT": "Редактировать комментарий",
"EDITED_COMMENT": "Изменено:",
"SHOW_HISTORY": "View historic",
"TYPE_NEW_COMMENT": "Добавить комментарий", "TYPE_NEW_COMMENT": "Добавить комментарий",
"SHOW_DELETED": "Показать удаленный комментарий", "SHOW_DELETED": "Показать удаленный комментарий",
"HIDE_DELETED": "Скрыть удаленный комментарий", "HIDE_DELETED": "Скрыть удаленный комментарий",
"DELETE": "Удалить комментарий", "DELETE": "Удалить комментарий",
"RESTORE": "Показать удаленный комментарий" "RESTORE": "Показать удаленный комментарий",
"HISTORY": {
"TITLE": "Действия"
}
}, },
"ACTIVITY": { "ACTIVITY": {
"SHOW_ACTIVITY": "Показать действия", "SHOW_ACTIVITY": "Показать действия",
"DATETIME": "DD MMM YYYY HH:mm", "DATETIME": "DD MMM YYYY HH:mm",
"SHOW_MORE": "+ Показать предыдущие записи (ещё {{showMore}})", "SHOW_MORE": "+ Показать предыдущие записи (ещё {{showMore}})",
"TITLE": "Действия", "TITLE": "Действия",
"ACTIVITIES_COUNT": "{{activities}} Activities",
"REMOVED": "удален", "REMOVED": "удален",
"ADDED": "добавлено", "ADDED": "добавлено",
"US_POINTS": "ПИ очки ({{name}})", "TAGS_ADDED": "тэги добавлены:",
"NEW_ATTACHMENT": "новое вложение", "TAGS_REMOVED": "tags removed:",
"DELETED_ATTACHMENT": "удаленное вложение", "US_POINTS": "{{role}} points",
"UPDATED_ATTACHMENT": "обновлено приложение {{filename}}", "NEW_ATTACHMENT": "новое вложение:",
"DELETED_CUSTOM_ATTRIBUTE": "удалить атрибут", "DELETED_ATTACHMENT": "удалённое вложение:",
"UPDATED_ATTACHMENT": "updated attachment ({{filename}}):",
"CREATED_CUSTOM_ATTRIBUTE": "created custom attribute",
"UPDATED_CUSTOM_ATTRIBUTE": "updated custom attribute",
"SIZE_CHANGE": "Сделано {size, plural, one{изменение} other{# изменений}}", "SIZE_CHANGE": "Сделано {size, plural, one{изменение} other{# изменений}}",
"BECAME_DEPRECATED": "became deprecated",
"BECAME_UNDEPRECATED": "became undeprecated",
"TEAM_REQUIREMENT": "Требование от Команды",
"CLIENT_REQUIREMENT": "Требование клиента",
"BLOCKED": "Заблокирован",
"VALUES": { "VALUES": {
"YES": "да", "YES": "да",
"NO": "нет", "NO": "нет",
@ -1052,12 +1198,14 @@
"TAGS": "тэги", "TAGS": "тэги",
"ATTACHMENTS": "Вложения", "ATTACHMENTS": "Вложения",
"IS_DEPRECATED": "рекомендовано", "IS_DEPRECATED": "рекомендовано",
"IS_NOT_DEPRECATED": "is not deprecated",
"ORDER": "порядок", "ORDER": "порядок",
"BACKLOG_ORDER": "порядок списка задач", "BACKLOG_ORDER": "порядок списка задач",
"SPRINT_ORDER": "порядок спринтов", "SPRINT_ORDER": "порядок спринтов",
"KANBAN_ORDER": "порядок kanban", "KANBAN_ORDER": "порядок kanban",
"TASKBOARD_ORDER": "порядок панели задач", "TASKBOARD_ORDER": "порядок панели задач",
"US_ORDER": "порядок ПИ" "US_ORDER": "порядок ПИ",
"COLOR": "цвет"
} }
}, },
"BACKLOG": { "BACKLOG": {
@ -1109,7 +1257,8 @@
"CLOSED_TASKS": "завершённые <br /> задачи", "CLOSED_TASKS": "завершённые <br /> задачи",
"IOCAINE_DOSES": "иокаина<br />дозы", "IOCAINE_DOSES": "иокаина<br />дозы",
"SHOW_STATISTICS_TITLE": "Показать статистику", "SHOW_STATISTICS_TITLE": "Показать статистику",
"TOGGLE_BAKLOG_GRAPH": "Показать/Скрыть график решения задач" "TOGGLE_BAKLOG_GRAPH": "Показать/Скрыть график решения задач",
"POINTS_PER_ROLE": "Points per role"
}, },
"SUMMARY": { "SUMMARY": {
"PROJECT_POINTS": "проектные<br />очки", "PROJECT_POINTS": "проектные<br />очки",
@ -1122,9 +1271,7 @@
"TITLE": "Фильтры", "TITLE": "Фильтры",
"REMOVE": "Сбросить фильтры", "REMOVE": "Сбросить фильтры",
"HIDE": "Спрятать фильтры", "HIDE": "Спрятать фильтры",
"SHOW": "Показать фильтры", "SHOW": "Показать фильтры"
"FILTER_CATEGORY_STATUS": "Статус",
"FILTER_CATEGORY_TAGS": "Тэги"
}, },
"SPRINTS": { "SPRINTS": {
"TITLE": "СПРИНТЫ", "TITLE": "СПРИНТЫ",
@ -1179,7 +1326,7 @@
"TASK": { "TASK": {
"PAGE_TITLE": "{{taskSubject}} - Задача {{taskRef}} - {{projectName}}", "PAGE_TITLE": "{{taskSubject}} - Задача {{taskRef}} - {{projectName}}",
"PAGE_DESCRIPTION": "Статус: {{taskStatus }}. Описание: {{taskDescription}}", "PAGE_DESCRIPTION": "Статус: {{taskStatus }}. Описание: {{taskDescription}}",
"SECTION_NAME": "Детали задачи", "SECTION_NAME": "Задача",
"LINK_TASKBOARD": "Панель задач", "LINK_TASKBOARD": "Панель задач",
"TITLE_LINK_TASKBOARD": "Перейти к панели задач", "TITLE_LINK_TASKBOARD": "Перейти к панели задач",
"PLACEHOLDER_SUBJECT": "Укажите новое название задачи", "PLACEHOLDER_SUBJECT": "Укажите новое название задачи",
@ -1189,8 +1336,6 @@
"ORIGIN_US": "Эта задача была создана из", "ORIGIN_US": "Эта задача была создана из",
"TITLE_LINK_GO_ORIGIN": "Перейти к пользовательской истории", "TITLE_LINK_GO_ORIGIN": "Перейти к пользовательской истории",
"BLOCKED": "Эта задача заблокирована", "BLOCKED": "Эта задача заблокирована",
"PREVIOUS": "предыдущая задача",
"NEXT": "следующая задача",
"TITLE_DELETE_ACTION": "Удалить задачу", "TITLE_DELETE_ACTION": "Удалить задачу",
"LIGHTBOX_TITLE_BLOKING_TASK": "Блокирующее задание", "LIGHTBOX_TITLE_BLOKING_TASK": "Блокирующее задание",
"FIELDS": { "FIELDS": {
@ -1218,26 +1363,23 @@
"SUCCESS": "Oompa Loompas удалил ваш аккаунт" "SUCCESS": "Oompa Loompas удалил ваш аккаунт"
}, },
"CHANGE_EMAIL_FORM": { "CHANGE_EMAIL_FORM": {
"TITLE": "Изменить e-mail", "TITLE": "Сменить вашу электронную почту",
"SUBTITLE": "Ещё один клик и Ваш email будет обновлён!", "SUBTITLE": "Ещё один клик и Ваш email будет обновлён!",
"PLACEHOLDER_INPUT_TOKEN": "изменить идентификатор email", "PLACEHOLDER_INPUT_TOKEN": "изменить идентификатор email",
"ACTION_CHANGE_EMAIL": "изменить почту", "ACTION_CHANGE_EMAIL": "Сменить электронную почту",
"SUCCESS": "Oompa Loompas обновил ваш e-mail" "SUCCESS": "Наш Oompa Loompas обновил вашу электронную почту"
}, },
"ISSUES": { "ISSUES": {
"PAGE_TITLE": "Запросы - {{projectName}}", "PAGE_TITLE": "Запросы - {{projectName}}",
"PAGE_DESCRIPTION": "Панель запросов проекта {{projectName}}: {{projectDescription}}", "PAGE_DESCRIPTION": "Панель запросов проекта {{projectName}}: {{projectDescription}}",
"LIST_SECTION_NAME": "Запросы", "LIST_SECTION_NAME": "Запросы",
"SECTION_NAME": "Детали запроса", "SECTION_NAME": "Запрос",
"ACTION_NEW_ISSUE": "+НОВЫЙ ЗАПРОС", "ACTION_NEW_ISSUE": "+НОВЫЙ ЗАПРОС",
"ACTION_PROMOTE_TO_US": "Повысить до пользовательской истории", "ACTION_PROMOTE_TO_US": "Повысить до пользовательской истории",
"PLACEHOLDER_FILTER_NAME": "Введите название фильтра и нажмите \"ввод\"",
"PROMOTED": "Этот запрос был переделан в ПИ:", "PROMOTED": "Этот запрос был переделан в ПИ:",
"EXTERNAL_REFERENCE": "Этот запрос был создан из", "EXTERNAL_REFERENCE": "Этот запрос был создан из",
"GO_TO_EXTERNAL_REFERENCE": "Перейти в начало", "GO_TO_EXTERNAL_REFERENCE": "Перейти в начало",
"BLOCKED": "Этот запрос заблокирована", "BLOCKED": "Этот запрос заблокирована",
"TITLE_PREVIOUS_ISSUE": "предыдущий запрос",
"TITLE_NEXT_ISSUE": "следующий запрос",
"ACTION_DELETE": "Удалить запрос", "ACTION_DELETE": "Удалить запрос",
"LIGHTBOX_TITLE_BLOKING_ISSUE": "Блокирующий запрос", "LIGHTBOX_TITLE_BLOKING_ISSUE": "Блокирующий запрос",
"FIELDS": { "FIELDS": {
@ -1249,28 +1391,6 @@
"TITLE": "Превратить этот запрос в новую пользовательскую историю", "TITLE": "Превратить этот запрос в новую пользовательскую историю",
"MESSAGE": "Вы уверены, что хотите создать новую ПИ из этого запроса?" "MESSAGE": "Вы уверены, что хотите создать новую ПИ из этого запроса?"
}, },
"FILTERS": {
"TITLE": "Фильтры",
"INPUT_SEARCH_PLACEHOLDER": "Название ссылки",
"TITLE_ACTION_SEARCH": "Поиск",
"ACTION_SAVE_CUSTOM_FILTER": "сохранить как специальный фильтр",
"BREADCRUMB": "Фильтры",
"TITLE_BREADCRUMB": "Фильтры",
"CATEGORIES": {
"TYPE": "Тип",
"STATUS": "Статус",
"SEVERITY": "Важность",
"PRIORITIES": "Приоритет",
"TAGS": "Тэги",
"ASSIGNED_TO": "Назначено",
"CREATED_BY": "Создано",
"CUSTOM_FILTERS": "Собственные фильтры"
},
"CONFIRM_DELETE": {
"TITLE": "Удалить фильтр",
"MESSAGE": "специальный фильтр '{{customFilterName}}'"
}
},
"TABLE": { "TABLE": {
"COLUMNS": { "COLUMNS": {
"TYPE": "Тип", "TYPE": "Тип",
@ -1316,6 +1436,7 @@
"SEARCH": { "SEARCH": {
"PAGE_TITLE": "Поиск - {{projectName}}", "PAGE_TITLE": "Поиск - {{projectName}}",
"PAGE_DESCRIPTION": "Ищите что угодно, пользовательские истории, задачи, запросы и вики-страницы, в проекте {{projectName}}: {{projectDescription}}", "PAGE_DESCRIPTION": "Ищите что угодно, пользовательские истории, задачи, запросы и вики-страницы, в проекте {{projectName}}: {{projectDescription}}",
"FILTER_EPICS": "Epics",
"FILTER_USER_STORIES": "Пользовательские Истории", "FILTER_USER_STORIES": "Пользовательские Истории",
"FILTER_ISSUES": "Запросы", "FILTER_ISSUES": "Запросы",
"FILTER_TASKS": "Задачи", "FILTER_TASKS": "Задачи",
@ -1383,7 +1504,7 @@
"CHANGE_PHOTO": "Изменить фото", "CHANGE_PHOTO": "Изменить фото",
"FIELD": { "FIELD": {
"USERNAME": "Имя пользователя", "USERNAME": "Имя пользователя",
"EMAIL": "Email", "EMAIL": "Электронная почта",
"FULL_NAME": "Полное имя", "FULL_NAME": "Полное имя",
"PLACEHOLDER_FULL_NAME": "Полное имя (например, Игорь Николаев)", "PLACEHOLDER_FULL_NAME": "Полное имя (например, Игорь Николаев)",
"BIO": "Биография (не более 210 символов)", "BIO": "Биография (не более 210 символов)",
@ -1399,10 +1520,10 @@
"CREATE_PROJECT_TEXT": "Свежий и чистый! Так здóрово!", "CREATE_PROJECT_TEXT": "Свежий и чистый! Так здóрово!",
"CHOOSE_TEMPLATE": "Which template fits your project best?", "CHOOSE_TEMPLATE": "Which template fits your project best?",
"CHOOSE_TEMPLATE_TITLE": "More info about project templates", "CHOOSE_TEMPLATE_TITLE": "More info about project templates",
"CHOOSE_TEMPLATE_INFO": "More info", "CHOOSE_TEMPLATE_INFO": "Больше инфо",
"PROJECT_DETAILS": "Project Details", "PROJECT_DETAILS": "Project Details",
"PUBLIC_PROJECT": "Public Project", "PUBLIC_PROJECT": "Public Project",
"PRIVATE_PROJECT": "Private Project", "PRIVATE_PROJECT": "Частный проект",
"CREATE_PROJECT": "Создать проект", "CREATE_PROJECT": "Создать проект",
"MAX_PRIVATE_PROJECTS": "You've reached the maximum number of private projects", "MAX_PRIVATE_PROJECTS": "You've reached the maximum number of private projects",
"MAX_PUBLIC_PROJECTS": "Unfortunately, you've reached the maximum number of public projects", "MAX_PUBLIC_PROJECTS": "Unfortunately, you've reached the maximum number of public projects",
@ -1415,15 +1536,26 @@
"PLACEHOLDER_PAGE": "Создать вики страницу", "PLACEHOLDER_PAGE": "Создать вики страницу",
"REMOVE": "Удалить эту вики страницу", "REMOVE": "Удалить эту вики страницу",
"DELETE_LIGHTBOX_TITLE": "Удалить вики страницу", "DELETE_LIGHTBOX_TITLE": "Удалить вики страницу",
"DELETE_LINK_TITLE": "Delete Wiki link", "DELETE_LINK_TITLE": "Удалить ссылку wiki",
"NAVIGATION": { "NAVIGATION": {
"SECTION_NAME": "Ссылки", "HOME": "Главная страница",
"ACTION_ADD_LINK": "Добавить ссылку" "SECTION_NAME": "ЗАКЛАДКИ",
"ACTION_ADD_LINK": "Добавить закладку",
"ALL_PAGES": "All wiki pages"
}, },
"SUMMARY": { "SUMMARY": {
"TIMES_EDITED": "раз <br />отредактировано", "TIMES_EDITED": "раз <br />отредактировано",
"LAST_EDIT": "последняя <br/> правка", "LAST_EDIT": "последняя <br/> правка",
"LAST_MODIFICATION": "последнее изменение" "LAST_MODIFICATION": "последнее изменение"
},
"SECTION_PAGES_LIST": "Все страницы",
"PAGES_LIST_COLUMNS": {
"TITLE": "Title",
"EDITIONS": "Editions",
"CREATED": "Создан",
"MODIFIED": "Modified",
"CREATOR": "Creator",
"LAST_MODIFIER": "Last modifier"
} }
}, },
"HINTS": { "HINTS": {
@ -1447,6 +1579,8 @@
"TASK_CREATED_WITH_US": "{{username}} создал новую задачу {{obj_name}} в {{project_name}}, которая принадлежит ПИ {{us_name}}", "TASK_CREATED_WITH_US": "{{username}} создал новую задачу {{obj_name}} в {{project_name}}, которая принадлежит ПИ {{us_name}}",
"WIKI_CREATED": "{{username}} создал новую вики-страницу {{obj_name}} в {{project_name}}", "WIKI_CREATED": "{{username}} создал новую вики-страницу {{obj_name}} в {{project_name}}",
"MILESTONE_CREATED": "{{username}} создал новый спринт {{obj_name}} в {{project_name}}", "MILESTONE_CREATED": "{{username}} создал новый спринт {{obj_name}} в {{project_name}}",
"EPIC_CREATED": "{{username}} has created a new epic {{obj_name}} in {{project_name}}",
"EPIC_RELATED_USERSTORY_CREATED": "{{username}} has related the userstory {{related_us_name}} to the epic {{epic_name}} in {{project_name}}",
"NEW_PROJECT": "{{username}} создал проект {{project_name}}", "NEW_PROJECT": "{{username}} создал проект {{project_name}}",
"MILESTONE_UPDATED": "{{username}} обновил спринт {{obj_name}}", "MILESTONE_UPDATED": "{{username}} обновил спринт {{obj_name}}",
"US_UPDATED": "{{username}} обновил атрибут \"{{field_name}}\" ПИ {{obj_name}}", "US_UPDATED": "{{username}} обновил атрибут \"{{field_name}}\" ПИ {{obj_name}}",
@ -1459,9 +1593,13 @@
"TASK_UPDATED_WITH_US": "{{username}} изменил атрибут \"{{field_name}}\" задачи {{obj_name}}, которая принадлежит ПИ {{us_name}}", "TASK_UPDATED_WITH_US": "{{username}} изменил атрибут \"{{field_name}}\" задачи {{obj_name}}, которая принадлежит ПИ {{us_name}}",
"TASK_UPDATED_WITH_US_NEW_VALUE": "{{username}} установил атрибут \"{{field_name}}\" задачи {{obj_name}}, которая принадлежит ПИ {{us_name}}, на {{new_value}}", "TASK_UPDATED_WITH_US_NEW_VALUE": "{{username}} установил атрибут \"{{field_name}}\" задачи {{obj_name}}, которая принадлежит ПИ {{us_name}}, на {{new_value}}",
"WIKI_UPDATED": "{{username}} обновил вики-страницу {{obj_name}}", "WIKI_UPDATED": "{{username}} обновил вики-страницу {{obj_name}}",
"EPIC_UPDATED": "{{username}} has updated the attribute \"{{field_name}}\" of the epic {{obj_name}}",
"EPIC_UPDATED_WITH_NEW_VALUE": "{{username}} has updated the attribute \"{{field_name}}\" of the epic {{obj_name}} to {{new_value}}",
"EPIC_UPDATED_WITH_NEW_COLOR": "{{username}} has updated the \"{{field_name}}\" of the epic {{obj_name}} to <span class=\"new-color\" style=\"background: {{new_value}}\"></span>",
"NEW_COMMENT_US": "{{username}} прокомментировал ПИ {{obj_name}}", "NEW_COMMENT_US": "{{username}} прокомментировал ПИ {{obj_name}}",
"NEW_COMMENT_ISSUE": "{{username}} прокомментировал запрос {{obj_name}}", "NEW_COMMENT_ISSUE": "{{username}} прокомментировал запрос {{obj_name}}",
"NEW_COMMENT_TASK": "{{username}} прокомментировал задачу {{obj_name}}", "NEW_COMMENT_TASK": "{{username}} прокомментировал задачу {{obj_name}}",
"NEW_COMMENT_EPIC": "{{username}} has commented in the epic {{obj_name}}",
"NEW_MEMBER": "У {{project_name}} появился новый участник", "NEW_MEMBER": "У {{project_name}} появился новый участник",
"US_ADDED_MILESTONE": "{{username}} добавил ПИ {{obj_name}} для {{sprint_name}}", "US_ADDED_MILESTONE": "{{username}} добавил ПИ {{obj_name}} для {{sprint_name}}",
"US_MOVED": "{{username}} переместил ПИ {{obj_name}}", "US_MOVED": "{{username}} переместил ПИ {{obj_name}}",

Some files were not shown because too many files have changed in this diff Show More