Compare commits

..

272 Commits

Author SHA1 Message Date
4aad488707 chore: group return parameter
Some checks reported errors
continuous-integration/drone/pr Build was killed
2023-05-31 14:18:58 +00:00
61f0f5210a chore: make fuzzy matching a paramater 2023-05-31 14:18:58 +00:00
8ea27a6655 fix: make type singular 2023-05-31 14:18:58 +00:00
4993673d5c chore(i18n): clarify translation string 2023-05-31 14:18:58 +00:00
1510807164 chore: use startsWith for prefix matching 2023-05-31 14:18:58 +00:00
a99eb820eb fix: clarify user search setting 2023-05-31 14:18:58 +00:00
ef65853278 chore: remove user margin from the component 2023-05-31 14:18:58 +00:00
0bb6085fb1 chore: remove user margin from the component 2023-05-31 14:18:58 +00:00
ede1069577 feat(quick add magic): allow fuzzy matching of assignees when the api results are unambigous 2023-05-31 14:18:58 +00:00
15a5aedcf9 fix: ensure all matched quick add magic parts are correctly removed from the task 2023-05-31 14:18:58 +00:00
5f29624414 fix: lint 2023-05-31 14:18:58 +00:00
502241a173 feat(assignees): show user avatar in search results 2023-05-31 14:18:58 +00:00
7df5a0ba2e feat: show initial list of users when opening the assignees view 2023-05-31 14:18:58 +00:00
1d05675cbd chore: clarify users when can still be found even if they disabled it 2023-05-31 14:18:58 +00:00
0fcf949653 fix(quick add magic): cleanup all assignee properties 2023-05-31 14:18:58 +00:00
22c10d935a fix(quick add magic): use the project user service to find assignees for quick add magic 2023-05-31 14:18:58 +00:00
3d0753ebc8 fix(quick add magic): don't replace the prefix in every occurrence when it is present in the matched part 2023-05-31 14:18:58 +00:00
8a75790453
chore: remove triggered notifications as it's not supported anywhere
Some checks reported errors
continuous-integration/drone/push Build encountered an error
2023-05-31 15:21:09 +02:00
acb212ab24
feat: set the current language to the one saved by the user on login 2023-05-31 15:17:54 +02:00
4ba02ebbb6
fix: don't try to convert a null date
All checks were successful
continuous-integration/drone/push Build is passing
Resolves #3371
2023-05-31 15:07:23 +02:00
244da46e38
fix(navigation): nav item width for items without sub projects
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-31 14:37:57 +02:00
f40035dc79
chore: update nix flake
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-31 13:44:14 +02:00
5f71e406fc fix(deps): update dependency marked to v5.0.4
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-31 05:15:46 +00:00
Frederick [Bot]
3d11a4f03a [skip ci] Updated translations via Crowdin 2023-05-31 00:30:36 +00:00
1dfd2dc4b7 fix(deps): update dependency vue-router to v4.2.2
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-30 22:46:00 +00:00
e9701660d3 chore(deps): update dependency vite-plugin-pwa to v0.15.2
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-05-30 21:04:22 +00:00
c8dbb4c7ef chore(deps): update typescript-eslint monorepo to v5.59.8
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-30 20:31:05 +00:00
1241d90268 chore(deps): update workbox monorepo to v6.6.1 (#3553)
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #3553
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2023-05-30 20:30:46 +00:00
3de5b65977 chore(deps): update dependency vitest to v0.31.2
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-30 18:45:05 +00:00
4a353553c3 chore(deps): update pnpm to v8.6.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-30 18:42:51 +00:00
1240f31c0a chore(deps): update workbox monorepo to v6.6.0 (#3548)
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #3548
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2023-05-30 18:12:03 +00:00
01ac84ce1e
fix: don't require variant prop on loading component as it already has a default one set
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-30 20:00:02 +02:00
4c969f0a42
fix: don't allow creating a new label from filter view
All checks were successful
continuous-integration/drone/push Build is passing
Resolves #1035
2023-05-30 19:54:01 +02:00
8e2c76a33e
feat: optimize print view for project views
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-30 19:50:37 +02:00
b3666ec27e chore(deps): update dependency @vitejs/plugin-legacy to v4.0.4
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-30 16:36:54 +00:00
2c6862c509 chore(deps): update dependency vite-plugin-pwa to v0.15.1
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-30 16:36:44 +00:00
9f8c43818c chore(deps): update dependency @types/node to v18.16.16
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-30 16:36:17 +00:00
0debca91c8 chore(deps): update dependency @faker-js/faker to v8.0.2
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-30 16:36:08 +00:00
7b6c9fcd24 chore(deps): update dependency postcss to v8.4.24
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-05-30 15:05:47 +00:00
55675bf41b fix(deps): update sentry-javascript monorepo to v7.53.1
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-30 14:25:03 +00:00
bb24b06031 chore(deps): update dependency vite to v4.3.9
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-30 14:24:37 +00:00
dbce0376d5 fix(deps): update dependency marked to v5.0.3
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-30 14:24:15 +00:00
40db144a41 fix(deps): update dependency @intlify/unplugin-vue-i18n to v0.11.0
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-05-30 11:08:12 +00:00
f7ba3bd08f
fix: increase default auto-save timeout to 5 seconds
Some checks failed
continuous-integration/drone/push Build is failing
Related discussion: https://community.vikunja.io/t/task-description-constantly-saving-loosing-content/1350
2023-05-30 12:19:14 +02:00
ac1d374191 feat: remove namespaces, make projects infinitely nestable (#3323)
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #3323
2023-05-30 10:09:39 +00:00
391992effb
fix: missing await
All checks were successful
continuous-integration/drone/pr Build is passing
2023-05-30 11:37:45 +02:00
2e9ade11c3
fix: missing variant prop for loading component
Some checks reported errors
continuous-integration/drone/pr Build was killed
2023-05-30 11:05:10 +02:00
f11a8c543b
fix(tests): project archived filter checkbox selector 2023-05-30 11:00:30 +02:00
e30a4452f2
fix(tests): new project input field 2023-05-30 10:57:08 +02:00
6cc11e64ab
fix: undefined parent project when none was selected 2023-05-30 10:56:42 +02:00
7b05ed9d3d
fix: avoid crashing browser processes during tests
Some checks reported errors
continuous-integration/drone/pr Build was killed
2023-05-30 10:42:32 +02:00
Frederick [Bot]
dba35c0107 [skip ci] Updated translations via Crowdin 2023-05-29 00:28:01 +00:00
Frederick [Bot]
bfbc874b1d [skip ci] Updated translations via Crowdin 2023-05-28 00:29:34 +00:00
dbccdb239a
chore(tests): enable experimental memory managment for cypress tests
Some checks failed
continuous-integration/drone/pr Build is failing
2023-05-24 18:32:23 +02:00
f13db9268a
fix: translation string 2023-05-24 17:41:14 +02:00
ed8de7e3eb
fix: lint
Some checks failed
continuous-integration/drone/pr Build is failing
2023-05-24 15:54:37 +02:00
b34118485c
feat: allow creating a new project directly as a child project from another one 2023-05-24 15:54:37 +02:00
9c3259c660
chore: don't recalculate everything 2023-05-24 15:54:37 +02:00
a3e289c06c
chore: remove type annotation for computed 2023-05-24 15:54:37 +02:00
31b7c1f217
fix: don't set the current project when setting a project 2023-05-24 15:54:37 +02:00
c30dcff451
chore: don't show selection for parent project when no projects are available 2023-05-24 15:54:37 +02:00
086f50d4fe
chore: re-add top menu spacing 2023-05-24 15:54:36 +02:00
46e825820c
fix: sort in store 2023-05-24 15:54:36 +02:00
a3e2cbeb27
feat: replace color dot with handle icon on hover 2023-05-24 15:54:36 +02:00
a342ae67de
chore: use project id type 2023-05-24 15:54:36 +02:00
e4d97e0520
chore: don't set the current project to null if it's undefined already 2023-05-24 15:54:36 +02:00
b69a05689b
chore: move duplicate project logic to composable 2023-05-24 15:54:36 +02:00
6b824a49ab
chore: redirect to new project after creating from store 2023-05-24 15:54:36 +02:00
652db56d42
chore: remove unused code 2023-05-24 15:54:36 +02:00
afaf1846ec
chore: don't wrap a computed in another computed 2023-05-24 15:54:36 +02:00
ba452ab883
fix: move parent project handling out of useProject 2023-05-24 15:54:36 +02:00
39f699a61a
fix: rename getParentProjects method to make it clear what it does 2023-05-24 15:54:36 +02:00
4ab547810c
fix: return updated project instead of the old one 2023-05-24 15:54:35 +02:00
bbaddb9406
fix: remove leftovers of childIds 2023-05-24 15:54:35 +02:00
a2cc9ddc88
fix: properly determine if there are projects 2023-05-24 15:54:35 +02:00
175e31ca62
fix: recreate project instead of editing before 2023-05-24 15:54:35 +02:00
d414b65e7d
fix: remove unnecessary fallback 2023-05-24 15:54:35 +02:00
78158bcba5
fix: remove getProjectById and replace all usages of it 2023-05-24 15:54:35 +02:00
9402344b7e
fix: add default for level 2023-05-24 15:54:35 +02:00
3eca9f6180
fix: only bind child projects data down 2023-05-24 15:54:35 +02:00
26e3d42ed5
fix: move parent project child id mutation to store 2023-05-24 15:54:35 +02:00
6e095436e9
chore: rename flag 2023-05-24 15:54:35 +02:00
1344026494
fix: move the collapsable placeholder to the button 2023-05-24 15:54:35 +02:00
1a94496801
fix: bottom margin of project header 2023-05-24 15:54:34 +02:00
48570808e5
fix: use the color bubble as handle if the project has a color 2023-05-24 15:54:34 +02:00
a7440ed296
chore: use stores directly 2023-05-24 15:54:34 +02:00
12ebefd86a
chore: move v-if 2023-05-24 15:54:34 +02:00
6c9cbaadc8
chore: set project id from the outside 2023-05-24 15:54:34 +02:00
9b10693172
chore: replace section with a div 2023-05-24 15:54:34 +02:00
db1c6d6a41
chore: move all options to component props 2023-05-24 15:54:34 +02:00
c56787443f
chore: add types for emit 2023-05-24 15:54:34 +02:00
cb218ec0c3
feat: add setting for infinite nesting 2023-05-24 15:54:34 +02:00
0dd6f82a0e
fix: use menu tag everywhere 2023-05-24 15:54:34 +02:00
225091864f
fix: collapsing child projects 2023-05-24 15:54:34 +02:00
ebd9c4702e
feat: don't use child_projects property from api 2023-05-24 15:54:33 +02:00
4ad9773022
chore: format 2023-05-24 15:54:33 +02:00
0a17df87e9
fix: don't show child projects when the project is only a favorite 2023-05-24 15:54:33 +02:00
b567146d69
chore: move more logic to ProjectsNavigationItem.vue 2023-05-24 15:54:33 +02:00
65522a57f1
chore: move ProjectsNavigationWrapper back to navigation.vue 2023-05-24 15:54:33 +02:00
1d936618fa
feat: load all projects earlier than in the navigation and use the loading state of the store 2023-05-24 15:54:33 +02:00
76814a2d3f
chore: move loading styles to variant into the component 2023-05-24 15:54:33 +02:00
4134fcbd75
chore: remove old comment 2023-05-24 15:54:33 +02:00
49fac7db1c
chore: use <menu> instead of <ul> 2023-05-24 15:54:33 +02:00
e25273df48
fix: indention 2023-05-24 15:54:33 +02:00
638f6bea24
chore: improve prop type definition 2023-05-24 15:54:33 +02:00
ddcd6a17dc
chore: only apply padding where needed 2023-05-24 15:54:32 +02:00
4e21b463df
chore: remove old todo 2023-05-24 15:54:32 +02:00
3db4e011d4
feat: move navigation item to component 2023-05-24 15:54:32 +02:00
a0d39e6081
chore: use long variable name 2023-05-24 15:54:32 +02:00
a803bc637e
chore: rename alias 2023-05-24 15:54:32 +02:00
d4e452545a
chore: remove unused class 2023-05-24 15:54:32 +02:00
9d73ac661f
fix: remove leftover suspense 2023-05-24 15:54:32 +02:00
55e912221b
chore: use klona to clone project objet 2023-05-24 15:54:32 +02:00
d85be26761
fix: passing readonly projects data to navigation 2023-05-24 15:54:32 +02:00
ac78e85e17
chore: move loader class 2023-05-24 15:54:32 +02:00
131022da42
chore: export favorite projects from store 2023-05-24 15:54:32 +02:00
336db56316
chore: remove unnecessary map 2023-05-24 15:54:32 +02:00
b5d9afd0f7
chore: export not archived root projects 2023-05-24 15:54:31 +02:00
0be83db40f
fix: show favorite on hover 2023-05-24 15:54:31 +02:00
03f4d0b8bc
fix: don't show > for top-level projects 2023-05-24 15:54:31 +02:00
ee8f80cc70
feat: allow selecting a parent project when editing a project 2023-05-24 15:54:31 +02:00
ce887c38f3
feat: allow selecting a parent project when creating a project 2023-05-24 15:54:31 +02:00
799c0be830
feat: allow selecting a parent project when duplicating a project 2023-05-24 15:54:31 +02:00
760efa854d
feat: don't handle child projects and instead only save the ids 2023-05-24 15:54:31 +02:00
26bec05174
fix: make computed side-effect free 2023-05-24 15:54:31 +02:00
c32a198a34
chore: refactor get parents project and move to projects store 2023-05-24 15:54:31 +02:00
6a8c656dbb
feat: show all parent projects in project search 2023-05-24 15:54:31 +02:00
63ba2982c9
feat: show all parent projects in task detail view 2023-05-24 15:54:30 +02:00
9d9fb959d8
fix: add await 2023-05-24 15:54:30 +02:00
8ed201c83f
fix(filters): load projects after updating a filter 2023-05-24 15:54:30 +02:00
bfb40c9166
fix(filters): load projects after deleting a filter 2023-05-24 15:54:30 +02:00
5ea450844c
fix(filters): load projects after creating a filter 2023-05-24 15:54:30 +02:00
36bec9e64f
chore(task): move toggleFavorite to store 2023-05-24 15:54:30 +02:00
a95014dc5d
feat(projects): move hasProjects check to store 2023-05-24 15:54:30 +02:00
2579c33ee1
feat: wrap projects navigation in a <Suspense> so that we can use top level await 2023-05-24 15:54:30 +02:00
6f1baa3219
chore: use long variable name 2023-05-24 15:54:30 +02:00
4dee3a90e9
chore: rename archived message key 2023-05-24 15:54:30 +02:00
326b6eda6f
fix: use correct shortcut to open projects overview 2023-05-24 15:54:30 +02:00
85e882cc59
fix: simplify sort 2023-05-24 15:54:29 +02:00
e4379f0a22
chore: export projects as array directly from projects store 2023-05-24 15:54:29 +02:00
2bb7ff1803
chore: rename prop 2023-05-24 15:54:29 +02:00
5dd6e9a077
feat(tests): add project tests derived from old namespace tests 2023-05-24 15:54:29 +02:00
f7629c28f4
fix(projects): make sure the project hierarchy is properly updated when moving projects between parents 2023-05-24 15:54:29 +02:00
be2a38b48e
feat(navigation): show favorite projects on top 2023-05-24 15:54:29 +02:00
3ba5f531bb
fix(navigation): make sure updating a project's state works for sub projects as well. 2023-05-24 15:54:29 +02:00
10f1e69bc3
fix(navigation): make marking a project as favorite work 2023-05-24 15:54:29 +02:00
fd7d90b017
fix(navigation): make sure the Favorites project shows up when marking or unmarking a task as favorite 2023-05-24 15:54:29 +02:00
d898316918
fix(navigation): favorites project 2023-05-24 15:54:29 +02:00
a6f524e7af
fix(task detail view): make project display show the task's project 2023-05-24 15:54:29 +02:00
5e65814b8c
fix: make check if projects are available work again 2023-05-24 15:54:28 +02:00
aaa9d553d0
fix: cleanup unused translation strings 2023-05-24 15:54:28 +02:00
5685890493
fix: make tests work again 2023-05-24 15:54:28 +02:00
2e336150e0
chore: cleanup namespace leftovers 2023-05-24 15:54:28 +02:00
749dcdcd70
fix(navigation): hide left ul border 2023-05-24 15:54:28 +02:00
ab94343d07
feat(navigation): make dragging a project under another project work 2023-05-24 15:54:28 +02:00
fa71cec5c8
feat(navigation): allow dragging a project out from its parent project 2023-05-24 15:54:28 +02:00
c6f3829387
feat(navigation): make dragging a project to a parent work 2023-05-24 15:54:28 +02:00
7171b63947
fix(navigation): hover state of other menu items 2023-05-24 15:54:28 +02:00
06c4c0d921
feat(navigation): add hiding child projects 2023-05-24 15:54:28 +02:00
f2ca2d850d
feat: translate inbox project title 2023-05-24 15:54:28 +02:00
638d187a24
chore: format 2023-05-24 15:54:28 +02:00
b188d40d3c
feat(navigation): correctly show child projects 2023-05-24 15:54:27 +02:00
3ad948305f
fix(navigation): make the styles work again 2023-05-24 15:54:27 +02:00
be1f1d94c9
fix(navigation): watcher 2023-05-24 15:54:27 +02:00
06e8cdb9d2
feat: rebuild main navigation so that it works recursively with projects 2023-05-24 15:54:27 +02:00
10311b79df
fix: remove namespace routes 2023-05-24 15:54:27 +02:00
ad2690b21c
fix: remove namespace store reference 2023-05-24 15:54:27 +02:00
1bd17d6e50
feat: remove all namespace leftovers 2023-05-24 15:54:27 +02:00
a5e710bfe5
fix: route to create new project 2023-05-24 15:54:27 +02:00
e1bdabc8d6
feat: move namespaces list to projects list 2023-05-24 15:54:27 +02:00
c6ef99dde2 chore(deps): update dependency cypress to v12.13.0
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-05-24 00:04:34 +00:00
49b508a783 fix(deps): update sentry-javascript monorepo to v7.53.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-23 15:50:03 +00:00
52128925f5 chore(deps): update typescript-eslint monorepo to v5.59.7
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-23 15:49:52 +00:00
cf0c7f9d08 chore(deps): update dependency rollup to v3.23.0
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-23 15:49:28 +00:00
57d5140301 chore(deps): update dependency @types/node to v18.16.14
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-05-23 12:04:31 +00:00
dbd9106621 chore(deps): update dependency postcss-preset-env to v8.4.1
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-23 11:17:17 +00:00
e4fef0e88e chore(deps): update dependency eslint to v8.41.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-23 11:16:31 +00:00
7ef0074ecc chore(deps): update dependency caniuse-lite to v1.0.30001489
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-23 11:16:09 +00:00
17c35f6d42 chore(deps): update dependency happy-dom to v9.20.1
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-23 11:15:58 +00:00
3a0844adba chore(deps): update dependency @rushstack/eslint-patch to v1.3.0
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-23 11:15:13 +00:00
5b5b9022e0 chore(deps): update dependency vite-plugin-pwa to v0.15.0
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-05-23 01:09:13 +00:00
Frederick [Bot]
0b0bd7dff6 [skip ci] Updated translations via Crowdin 2023-05-23 00:29:34 +00:00
079e3782d1 chore(deps): update dependency rollup to v3.22.0
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-19 10:30:44 +00:00
a0ae9ae54c chore(deps): update dependency @types/marked to v5
Some checks failed
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is failing
2023-05-19 09:06:04 +00:00
a1b9a0ec4c fix(deps): update dependency @kyvg/vue3-notification to v2.9.1
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-19 08:07:44 +00:00
1fa690670d fix(deps): update dependency vue-router to v4.2.1
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-19 08:06:23 +00:00
3f0a87a5ec chore(deps): update dependency vite to v4.3.8
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-19 08:05:46 +00:00
caf02f78bf chore(deps): update dependency @types/marked to v4.3.1
Some checks failed
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is failing
2023-05-18 23:05:09 +00:00
9b9fd14d27 chore(deps): update dependency vitest to v0.31.1
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-05-17 15:05:09 +00:00
7f77efbfab chore(deps): update dependency @types/node to v18.16.11
Some checks failed
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is failing
2023-05-16 20:04:54 +00:00
53967d20cc chore(deps): update dependency vite to v4.3.7
Some checks failed
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is failing
2023-05-16 17:05:08 +00:00
ef3411f39a chore(deps): update dependency @types/node to v18.16.10
Some checks failed
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is failing
2023-05-16 11:04:50 +00:00
66e63f1363 chore(deps): update typescript-eslint monorepo to v5.59.6
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-16 10:46:23 +00:00
2fe21f6b28 fix(deps): update sentry-javascript monorepo to v7.52.1
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-16 10:46:09 +00:00
67df372636 chore(deps): update dependency eslint-plugin-vue to v9.13.0
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-16 10:45:49 +00:00
df80e9da23 chore(deps): update dependency rollup to v3.21.8
Some checks failed
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is failing
2023-05-16 08:04:56 +00:00
13ab2efd0f chore(deps): update dependency @faker-js/faker to v8.0.1
Some checks failed
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is failing
2023-05-15 17:04:44 +00:00
0ffe96cf59 chore(deps): update dependency vite to v4.3.6
Some checks failed
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is failing
2023-05-15 16:04:58 +00:00
1808d0971d fix(deps): update sentry-javascript monorepo to v7.52.0
Some checks failed
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is failing
2023-05-15 14:05:00 +00:00
ec83a28d78 chore(deps): update pnpm to v8.5.1
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-15 10:33:06 +00:00
f0320b3a58 chore(deps): update dependency caniuse-lite to v1.0.30001487
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-15 10:30:51 +00:00
d93a1a4f4f chore(deps): update dependency happy-dom to v9.18.3
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-05-15 00:05:29 +00:00
a9f9ddf6b9 chore(deps): update dependency @types/node to v18.16.9
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-05-13 15:05:04 +00:00
6a8fe35fcf chore(deps): update dependency rollup to v3.21.7
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-13 14:48:00 +00:00
94661e9e09 chore(deps): update dependency vue-tsc to v1.6.5
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-05-13 08:04:55 +00:00
318f63d098 chore(deps): update dependency esbuild to v0.17.19
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-05-13 01:04:45 +00:00
e2c9e83c2a chore(deps): update dependency @vitejs/plugin-vue to v4.2.3
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-05-12 11:04:45 +00:00
cd434a0e3e chore(deps): update dependency @types/node to v18.16.8
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-12 07:06:52 +00:00
9f293af804 chore(deps): update dependency @vue/tsconfig to v0.4.0
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-12 07:06:24 +00:00
b175e00cfe chore(deps): update dependency @tsconfig/node18 to v2.0.1
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-05-12 05:04:41 +00:00
Frederick [Bot]
19dd82d62a [skip ci] Updated translations via Crowdin 2023-05-12 00:29:44 +00:00
b3ddc9465a chore(deps): update dependency @vitejs/plugin-vue to v4.2.2
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-11 19:57:40 +00:00
6b38f17d32 fix(deps): update dependency vue-router to v4.2.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-11 19:57:25 +00:00
86449d4912 fix(deps): update dependency marked to v5.0.2
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-11 19:57:07 +00:00
145d756251 chore(deps): update dependency @faker-js/faker to v8
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-05-11 18:05:10 +00:00
838a11a2f6 chore(deps): update dependency eslint-plugin-vue to v9.12.0
Some checks failed
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is failing
2023-05-10 14:04:39 +00:00
3bfd3210b0 chore(deps): update dependency @types/node to v18.16.7
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-10 09:46:06 +00:00
e933bfa99e fix(deps): update sentry-javascript monorepo to v7.51.2
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-10 09:14:43 +00:00
f6a37a54d0 fix(deps): update dependency pinia to v2.0.36
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-10 09:14:33 +00:00
e00c9bb1af feat: add hotkeys for priority, delete and favorite on the TaskDetailView (#3400)
Some checks failed
continuous-integration/drone/push Build is failing
Reviewed-on: #3400
Reviewed-by: konrad <k@knt.li>
Co-authored-by: primeapple <toni.mueller.web@mailbox.org>
Co-committed-by: primeapple <toni.mueller.web@mailbox.org>
2023-05-10 09:14:07 +00:00
018707c3d5
fix(ci): disable puppeteer chrome download
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-10 10:42:44 +02:00
386727f6c5 chore(deps): update dependency @types/node to v18.16.6
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-10 08:09:35 +00:00
a29ce36d6c chore(deps): update typescript-eslint monorepo to v5.59.5
Some checks failed
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is failing
2023-05-10 07:05:09 +00:00
7aed16bd6f chore(deps): update dependency rollup to v3.21.6
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-10 06:03:37 +00:00
b1f3ca6e59 chore(deps): update pnpm to v8.5.0
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-10 06:03:09 +00:00
4c0b8a06c5 chore(deps): update dependency cypress to v12.12.0
Some checks failed
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is failing
2023-05-09 23:05:25 +00:00
60647c50ac chore(deps): update dependency caniuse-lite to v1.0.30001486
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-08 07:11:25 +00:00
59eaf1849e chore(deps): update dependency happy-dom to v9.10.9
Some checks failed
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is failing
2023-05-08 00:05:41 +00:00
fb57339050 chore(deps): update dependency eslint-plugin-vue to v9.11.1
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-05-07 17:04:47 +00:00
f9831a6ad8 fix(deps): update dependency marked to v5.0.1
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-05-06 21:04:51 +00:00
f25c67f80a chore(deps): update dependency eslint to v8.40.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-06 15:26:02 +00:00
d3b0b97192 chore(deps): update dependency @types/node to v18.16.5
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-06 15:25:42 +00:00
fa3be219a8 fix(deps): update dependency dompurify to v3.0.3
Some checks failed
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is failing
2023-05-06 13:04:56 +00:00
c22702d911 chore(deps): update dependency @types/node to v18.16.4
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-05-05 14:04:43 +00:00
b25c5ff547 chore(deps): update dependency vite to v4.3.5
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-05-05 11:04:43 +00:00
2e0a097806 chore(deps): update dependency rollup to v3.21.5
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-05-05 05:04:46 +00:00
c2083f7924 fix(deps): update sentry-javascript monorepo to v7.51.0
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-05-04 16:05:24 +00:00
8923261e5b fix(deps): update dependency ufo to v1.1.2
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-04 07:35:00 +00:00
5391df56b0 chore(deps): update dependency vue-tsc to v1.6.4
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-05-04 01:04:54 +00:00
d2b1f5780e chore(deps): update dependency vitest to v0.31.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-03 19:52:49 +00:00
1717e968e1 chore(deps): update dependency rollup to v3.21.4
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-05-03 19:04:31 +00:00
2c29bb3971 chore(deps): update pnpm to v8.4.0
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-05-02 14:04:09 +00:00
37b8218a0a chore(deps): update node.js to v20 (#3411)
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #3411
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2023-05-02 13:35:04 +00:00
ca7bbb5b91 chore(ci): remove netlify dependency (#3459)
All checks were successful
continuous-integration/drone/push Build is passing
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: #3459
2023-05-02 10:10:14 +00:00
2f3c008d2b chore(deps): update dependency vite to v4.3.4
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-05-02 08:04:40 +00:00
c2722b7c3d fix(deps): update dependency @vueuse/core to v10.1.2
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-02 07:18:12 +00:00
312abd907f chore(deps): update dependency rollup to v3.21.3
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-02 07:18:02 +00:00
1b73c1ed64 chore(deps): update dependency vue-tsc to v1.6.3
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-02 07:17:43 +00:00
d442d6653b fix(deps): update dependency marked to v5
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-05-02 05:05:40 +00:00
758b8d6e2b chore(deps): update typescript-eslint monorepo to v5.59.2
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-05-01 18:04:39 +00:00
416fd2e2a7 chore(deps): update dependency @types/marked to v4.3.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-01 16:45:51 +00:00
15a8335f1a chore(deps): update dependency vue-tsc to v1.6.2
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-05-01 14:04:42 +00:00
c689583669 chore(deps): update dependency netlify-cli to v14.3.1
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-01 10:44:11 +00:00
7a43a7acc9 chore(deps): update dependency happy-dom to v9.10.1
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-05-01 00:04:51 +00:00
8843418161 fix(deps): update dependency date-fns to v2.30.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-30 06:57:42 +00:00
7c1eab13ae chore(deps): update dependency rollup to v3.21.2
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-04-30 06:04:44 +00:00
5a69036da7 fix(deps): update dependency highlight.js to v11.8.0
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-04-29 14:04:50 +00:00
2ad3458873 chore(deps): update dependency @types/node to v18.16.3
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-04-29 07:04:40 +00:00
eb464343e8 chore(deps): update dependency rollup to v3.21.1
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-04-29 06:04:42 +00:00
2f18d0cbad
fix(docker): don't set nginx worker rlimit
All checks were successful
continuous-integration/drone/push Build is passing
Resolves https://community.vikunja.io/t/helm-chart-frontend-pod-does-not-start-because-of-permission-issues-in-raspberry-pie-4-k3s/1286
2023-04-28 10:31:15 +02:00
6cd463a514 chore(deps): pin dependency @tsconfig/node18 to 2.0.0
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-04-28 08:04:35 +00:00
05b70632c5
fix: tsconfig as per https://github.com/vuejs/tsconfig#configuration-for-node-environments
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-04-28 09:30:45 +02:00
ca9fe6ff21
fix: tsconfig as per https://github.com/vuejs/tsconfig#configuration-for-node-environments
Some checks failed
continuous-integration/drone/pr Build is failing
2023-04-28 09:16:54 +02:00
e5754300de chore(deps): update dependency @vue/tsconfig to v0.3.2
Some checks failed
continuous-integration/drone/pr Build is failing
2023-04-28 07:04:31 +00:00
65134048bf chore(deps): update dependency @vitejs/plugin-vue to v4.2.1
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-28 06:04:35 +00:00
8339a99747 chore(deps): update dependency @types/node to v18.16.2
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-28 05:17:36 +00:00
3e1ae41e70 fix(deps): update dependency axios to v1.4.0
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-04-28 00:04:55 +00:00
f757ba3441 chore(deps): update dependency vue-tsc to v1.6.1
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-04-27 19:04:37 +00:00
6499c9cb5b fix(deps): update sentry-javascript monorepo to v7.50.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-27 09:39:32 +00:00
28e5440d8b fix(deps): update dependency codemirror to v5.65.13
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-04-27 09:04:38 +00:00
fef8c4d0f4 chore(deps): update dependency vue-tsc to v1.6.0
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-04-26 21:06:27 +00:00
99e5059c64 chore(deps): update dependency cypress to v12.11.0
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-04-26 18:04:42 +00:00
128 changed files with 3745 additions and 12134 deletions

View File

@ -42,11 +42,12 @@ steps:
# - .cache # - .cache
- name: dependencies - name: dependencies
image: node:18-alpine image: node:20-alpine
pull: always pull: always
environment: environment:
PNPM_CACHE_FOLDER: .cache/pnpm PNPM_CACHE_FOLDER: .cache/pnpm
CYPRESS_CACHE_FOLDER: .cache/cypress CYPRESS_CACHE_FOLDER: .cache/cypress
PUPPETEER_SKIP_DOWNLOAD: true
commands: commands:
- corepack enable && pnpm config set store-dir .cache/pnpm - corepack enable && pnpm config set store-dir .cache/pnpm
- pnpm install --fetch-timeout 100000 - pnpm install --fetch-timeout 100000
@ -54,7 +55,7 @@ steps:
# - restore-cache # - restore-cache
- name: lint - name: lint
image: node:18-alpine image: node:20-alpine
pull: always pull: always
environment: environment:
PNPM_CACHE_FOLDER: .cache/pnpm PNPM_CACHE_FOLDER: .cache/pnpm
@ -65,7 +66,7 @@ steps:
- dependencies - dependencies
- name: build-prod - name: build-prod
image: node:18-alpine image: node:20-alpine
pull: always pull: always
environment: environment:
PNPM_CACHE_FOLDER: .cache/pnpm PNPM_CACHE_FOLDER: .cache/pnpm
@ -76,7 +77,7 @@ steps:
- dependencies - dependencies
- name: test-unit - name: test-unit
image: node:18-alpine image: node:20-alpine
pull: always pull: always
commands: commands:
- corepack enable && pnpm config set store-dir .cache/pnpm - corepack enable && pnpm config set store-dir .cache/pnpm
@ -86,7 +87,7 @@ steps:
- name: typecheck - name: typecheck
failure: ignore failure: ignore
image: node:18-alpine image: node:20-alpine
pull: always pull: always
environment: environment:
PNPM_CACHE_FOLDER: .cache/pnpm PNPM_CACHE_FOLDER: .cache/pnpm
@ -136,8 +137,9 @@ steps:
# - dependencies # - dependencies
- name: deploy-preview - name: deploy-preview
image: node:18-alpine image: williamjackson/netlify-cli
pull: always pull: always
user: root # The rest runs as root and thus the permissions wouldn't work
environment: environment:
NETLIFY_AUTH_TOKEN: NETLIFY_AUTH_TOKEN:
from_secret: netlify_auth_token from_secret: netlify_auth_token
@ -200,7 +202,7 @@ steps:
# - .cache # - .cache
- name: build - name: build
image: node:18-alpine image: node:20-alpine
pull: always pull: always
environment: environment:
PNPM_CACHE_FOLDER: .cache/pnpm PNPM_CACHE_FOLDER: .cache/pnpm
@ -277,7 +279,7 @@ steps:
# - .cache # - .cache
- name: build - name: build
image: node:18-alpine image: node:20-alpine
pull: always pull: always
environment: environment:
PNPM_CACHE_FOLDER: .cache/pnpm PNPM_CACHE_FOLDER: .cache/pnpm
@ -522,6 +524,6 @@ steps:
from_secret: crowdin_key from_secret: crowdin_key
--- ---
kind: signature kind: signature
hmac: 303afeb09b75a57ba88720b45dc06c8bf2c7320e19d738d8299f325438246f75 hmac: 511c2a090e9efd4c942980d971204adb6321540bb01c92409dd9bf8463b7f6f4
... ...

View File

@ -3,7 +3,7 @@
# │─││ │││ │ │ # │─││ │││ │ │
# ┘─┘┘─┘┘┘─┘┘─┘ # ┘─┘┘─┘┘┘─┘┘─┘
FROM --platform=$BUILDPLATFORM node:18-alpine AS builder FROM --platform=$BUILDPLATFORM node:20-alpine AS builder
WORKDIR /build WORKDIR /build
@ -54,6 +54,7 @@ ENV VIKUNJA_LOG_FORMAT main
ENV VIKUNJA_API_URL /api/v1 ENV VIKUNJA_API_URL /api/v1
ENV VIKUNJA_SENTRY_ENABLED false ENV VIKUNJA_SENTRY_ENABLED false
ENV VIKUNJA_SENTRY_DSN https://85694a2d757547cbbc90cd4b55c5a18d@o1047380.ingest.sentry.io/6024480 ENV VIKUNJA_SENTRY_DSN https://85694a2d757547cbbc90cd4b55c5a18d@o1047380.ingest.sentry.io/6024480
ENV VIKUNJA_PROJECT_INFINITE_NESTING_ENABLED false
COPY docker/injector.sh /docker-entrypoint.d/50-injector.sh COPY docker/injector.sh /docker-entrypoint.d/50-injector.sh
COPY docker/ipv6-disable.sh /docker-entrypoint.d/60-ipv6-disable.sh COPY docker/ipv6-disable.sh /docker-entrypoint.d/60-ipv6-disable.sh

View File

@ -24,4 +24,5 @@ export default defineConfig({
}, },
viewportWidth: 1600, viewportWidth: 1600,
viewportHeight: 900, viewportHeight: 900,
experimentalMemoryManagement: true,
}) })

View File

@ -2,7 +2,6 @@ import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {TaskFactory} from '../../factories/task' import {TaskFactory} from '../../factories/task'
import {ProjectFactory} from '../../factories/project' import {ProjectFactory} from '../../factories/project'
import {NamespaceFactory} from '../../factories/namespace'
import {UserProjectFactory} from '../../factories/users_project' import {UserProjectFactory} from '../../factories/users_project'
import {BucketFactory} from '../../factories/bucket' import {BucketFactory} from '../../factories/bucket'
@ -10,7 +9,6 @@ describe('Editor', () => {
createFakeUserAndLogin() createFakeUserAndLogin()
beforeEach(() => { beforeEach(() => {
NamespaceFactory.create(1)
ProjectFactory.create(1) ProjectFactory.create(1)
BucketFactory.create(1) BucketFactory.create(1)
TaskFactory.truncate() TaskFactory.truncate()

View File

@ -8,20 +8,20 @@ describe('The Menu', () => {
}) })
it('Is visible by default on desktop', () => { it('Is visible by default on desktop', () => {
cy.get('.namespace-container') cy.get('.menu-container')
.should('have.class', 'is-active') .should('have.class', 'is-active')
}) })
it('Can be hidden on desktop', () => { it('Can be hidden on desktop', () => {
cy.get('button.menu-show-button:visible') cy.get('button.menu-show-button:visible')
.click() .click()
cy.get('.namespace-container') cy.get('.menu-container')
.should('not.have.class', 'is-active') .should('not.have.class', 'is-active')
}) })
it('Is hidden by default on mobile', () => { it('Is hidden by default on mobile', () => {
cy.viewport('iphone-8') cy.viewport('iphone-8')
cy.get('.namespace-container') cy.get('.menu-container')
.should('not.have.class', 'is-active') .should('not.have.class', 'is-active')
}) })
@ -29,7 +29,7 @@ describe('The Menu', () => {
cy.viewport('iphone-8') cy.viewport('iphone-8')
cy.get('button.menu-show-button:visible') cy.get('button.menu-show-button:visible')
.click() .click()
cy.get('.namespace-container') cy.get('.menu-container')
.should('have.class', 'is-active') .should('have.class', 'is-active')
}) })
}) })

View File

@ -1,145 +0,0 @@
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {ProjectFactory} from '../../factories/project'
import {NamespaceFactory} from '../../factories/namespace'
describe('Namepaces', () => {
createFakeUserAndLogin()
let namespaces
beforeEach(() => {
namespaces = NamespaceFactory.create(1)
ProjectFactory.create(1)
})
it('Should be all there', () => {
cy.visit('/namespaces')
cy.get('[data-cy="namespace-title"]')
.should('contain', namespaces[0].title)
})
it('Should create a new Namespace', () => {
const newNamespaceTitle = 'New Namespace'
cy.visit('/namespaces')
cy.get('[data-cy="new-namespace"]')
.should('contain', 'New namespace')
.click()
cy.url()
.should('contain', '/namespaces/new')
cy.get('.card-header-title')
.should('contain', 'New namespace')
cy.get('input.input')
.type(newNamespaceTitle)
cy.get('.button')
.contains('Create')
.click()
cy.get('.global-notification')
.should('contain', 'Success')
cy.get('.namespace-container')
.should('contain', newNamespaceTitle)
cy.url()
.should('contain', '/namespaces')
})
it('Should rename the namespace all places', () => {
const newNamespaces = NamespaceFactory.create(5)
const newNamespaceName = 'New namespace name'
cy.visit('/namespaces')
cy.get(`.namespace-container .menu.namespaces-lists .namespace-title:contains(${newNamespaces[0].title}) .dropdown .dropdown-trigger`)
.click()
cy.get('.namespace-container .menu.namespaces-lists .namespace-title .dropdown .dropdown-content')
.contains('Edit')
.click()
cy.url()
.should('contain', '/settings/edit')
cy.get('#namespacetext')
.invoke('val')
.should('equal', newNamespaces[0].title) // wait until the namespace data is loaded
cy.get('#namespacetext')
.type(`{selectall}${newNamespaceName}`)
cy.get('footer.card-footer .button')
.contains('Save')
.click()
cy.get('.global-notification', { timeout: 1000 })
.should('contain', 'Success')
cy.get('.namespace-container .menu.namespaces-lists')
.should('contain', newNamespaceName)
.should('not.contain', newNamespaces[0].title)
cy.get('[data-cy="namespaces-list"]')
.should('contain', newNamespaceName)
.should('not.contain', newNamespaces[0].title)
})
it('Should remove a namespace when deleting it', () => {
const newNamespaces = NamespaceFactory.create(5)
cy.visit('/')
cy.get(`.namespace-container .menu.namespaces-lists .namespace-title:contains(${newNamespaces[0].title}) .dropdown .dropdown-trigger`)
.click()
cy.get('.namespace-container .menu.namespaces-lists .namespace-title .dropdown .dropdown-content')
.contains('Delete')
.click()
cy.url()
.should('contain', '/settings/delete')
cy.get('[data-cy="modalPrimary"]')
.contains('Do it')
.click()
cy.get('.global-notification')
.should('contain', 'Success')
cy.get('.namespace-container .menu.namespaces-lists')
.should('not.contain', newNamespaces[0].title)
})
it('Should not show archived projects & namespaces if the filter is not checked', () => {
const n = NamespaceFactory.create(1, {
id: 2,
is_archived: true,
}, false)
ProjectFactory.create(1, {
id: 2,
namespace_id: n[0].id,
}, false)
ProjectFactory.create(1, {
id: 3,
is_archived: true,
}, false)
// Initial
cy.visit('/namespaces')
cy.get('.namespace')
.should('not.contain', 'Archived')
// Show archived
cy.get('[data-cy="show-archived-check"] .fancycheckbox__content')
.should('be.visible')
.click()
cy.get('[data-cy="show-archived-check"] input')
.should('be.checked')
cy.get('.namespace')
.should('contain', 'Archived')
// Don't show archived
cy.get('[data-cy="show-archived-check"] .fancycheckbox__content')
.should('be.visible')
.click()
cy.get('[data-cy="show-archived-check"] input')
.should('not.be.checked')
// Second time visiting after unchecking
cy.visit('/namespaces')
cy.get('[data-cy="show-archived-check"] input')
.should('not.be.checked')
cy.get('.namespace')
.should('not.contain', 'Archived')
})
})

View File

@ -1,9 +1,7 @@
import {ProjectFactory} from '../../factories/project' import {ProjectFactory} from '../../factories/project'
import {NamespaceFactory} from '../../factories/namespace'
import {TaskFactory} from '../../factories/task' import {TaskFactory} from '../../factories/task'
export function createProjects() { export function createProjects() {
NamespaceFactory.create(1)
const projects = ProjectFactory.create(1, { const projects = ProjectFactory.create(1, {
title: 'First Project' title: 'First Project'
}) })

View File

@ -8,37 +8,30 @@ describe('Project History', () => {
prepareProjects() prepareProjects()
it('should show a project history on the home page', () => { it('should show a project history on the home page', () => {
cy.intercept(Cypress.env('API_URL') + '/namespaces*').as('loadNamespaces') cy.intercept(Cypress.env('API_URL') + '/projects*').as('loadProjectArray')
cy.intercept(Cypress.env('API_URL') + '/projects/*').as('loadProject') cy.intercept(Cypress.env('API_URL') + '/projects/*').as('loadProject')
const projects = ProjectFactory.create(6) const projects = ProjectFactory.create(6)
cy.visit('/') cy.visit('/')
cy.wait('@loadNamespaces') cy.wait('@loadProjectArray')
cy.get('body') cy.get('body')
.should('not.contain', 'Last viewed') .should('not.contain', 'Last viewed')
cy.visit(`/projects/${projects[0].id}`) cy.visit(`/projects/${projects[0].id}`)
cy.wait('@loadNamespaces')
cy.wait('@loadProject') cy.wait('@loadProject')
cy.visit(`/projects/${projects[1].id}`) cy.visit(`/projects/${projects[1].id}`)
cy.wait('@loadNamespaces')
cy.wait('@loadProject') cy.wait('@loadProject')
cy.visit(`/projects/${projects[2].id}`) cy.visit(`/projects/${projects[2].id}`)
cy.wait('@loadNamespaces')
cy.wait('@loadProject') cy.wait('@loadProject')
cy.visit(`/projects/${projects[3].id}`) cy.visit(`/projects/${projects[3].id}`)
cy.wait('@loadNamespaces')
cy.wait('@loadProject') cy.wait('@loadProject')
cy.visit(`/projects/${projects[4].id}`) cy.visit(`/projects/${projects[4].id}`)
cy.wait('@loadNamespaces')
cy.wait('@loadProject') cy.wait('@loadProject')
cy.visit(`/projects/${projects[5].id}`) cy.visit(`/projects/${projects[5].id}`)
cy.wait('@loadNamespaces')
cy.wait('@loadProject') cy.wait('@loadProject')
// cy.visit('/') // cy.visit('/')
// cy.wait('@loadNamespaces')
// Not using cy.visit here to work around the redirect issue fixed in #1337 // Not using cy.visit here to work around the redirect issue fixed in #1337
cy.get('nav.menu.top-menu a') cy.get('nav.menu.top-menu a')
.contains('Overview') .contains('Overview')

View File

@ -58,7 +58,6 @@ describe('Project View Project', () => {
}) })
const projects = ProjectFactory.create(2, { const projects = ProjectFactory.create(2, {
owner_id: '{increment}', owner_id: '{increment}',
namespace_id: '{increment}',
}) })
cy.visit(`/projects/${projects[1].id}/`) cy.visit(`/projects/${projects[1].id}/`)

View File

@ -1,6 +1,7 @@
import {createFakeUserAndLogin} from '../../support/authenticateUser' import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {TaskFactory} from '../../factories/task' import {TaskFactory} from '../../factories/task'
import {ProjectFactory} from '../../factories/project'
import {prepareProjects} from './prepareProjects' import {prepareProjects} from './prepareProjects'
describe('Projects', () => { describe('Projects', () => {
@ -10,23 +11,20 @@ describe('Projects', () => {
prepareProjects((newProjects) => (projects = newProjects)) prepareProjects((newProjects) => (projects = newProjects))
it('Should create a new project', () => { it('Should create a new project', () => {
cy.visit('/') cy.visit('/projects')
cy.get('.namespace-title .dropdown-trigger') cy.get('.project-header [data-cy=new-project]')
.click()
cy.get('.namespace-title .dropdown .dropdown-item')
.contains('New project')
.click() .click()
cy.url() cy.url()
.should('contain', '/projects/new/1') .should('contain', '/projects/new')
cy.get('.card-header-title') cy.get('.card-header-title')
.contains('New project') .contains('New project')
cy.get('input.input') cy.get('input[name=projectTitle]')
.type('New Project') .type('New Project')
cy.get('.button') cy.get('.button')
.contains('Create') .contains('Create')
.click() .click()
cy.get('.global-notification', { timeout: 1000 }) // Waiting until the request to create the new project is done cy.get('.global-notification', {timeout: 1000}) // Waiting until the request to create the new project is done
.should('contain', 'Success') .should('contain', 'Success')
cy.url() cy.url()
.should('contain', '/projects/') .should('contain', '/projects/')
@ -56,9 +54,9 @@ describe('Projects', () => {
cy.get('.project-title') cy.get('.project-title')
.should('contain', 'First Project') .should('contain', 'First Project')
cy.get('.namespace-container .menu.namespaces-lists .menu-list li:first-child .dropdown .menu-list-dropdown-trigger') cy.get('.menu-container .menu-list li:first-child .dropdown .menu-list-dropdown-trigger')
.click() .click()
cy.get('.namespace-container .menu.namespaces-lists .menu-list li:first-child .dropdown .dropdown-content') cy.get('.menu-container .menu-list li:first-child .dropdown .dropdown-content')
.contains('Edit') .contains('Edit')
.click() .click()
cy.get('#title') cy.get('#title')
@ -72,21 +70,21 @@ describe('Projects', () => {
cy.get('.project-title') cy.get('.project-title')
.should('contain', newProjectName) .should('contain', newProjectName)
.should('not.contain', projects[0].title) .should('not.contain', projects[0].title)
cy.get('.namespace-container .menu.namespaces-lists .menu-list li:first-child') cy.get('.menu-container .menu-list li:first-child')
.should('contain', newProjectName) .should('contain', newProjectName)
.should('not.contain', projects[0].title) .should('not.contain', projects[0].title)
cy.visit('/') cy.visit('/')
cy.get('.card-content') cy.get('.project-grid')
.should('contain', newProjectName) .should('contain', newProjectName)
.should('not.contain', projects[0].title) .should('not.contain', projects[0].title)
}) })
it('Should remove a project', () => { it('Should remove a project when deleting it', () => {
cy.visit(`/projects/${projects[0].id}`) cy.visit(`/projects/${projects[0].id}`)
cy.get('.namespace-container .menu.namespaces-lists .menu-list li:first-child .dropdown .menu-list-dropdown-trigger') cy.get('.menu-container .menu-list li:first-child .dropdown .menu-list-dropdown-trigger')
.click() .click()
cy.get('.namespace-container .menu.namespaces-lists .menu-list li:first-child .dropdown .dropdown-content') cy.get('.menu-container .menu-list li:first-child .dropdown .dropdown-content')
.contains('Delete') .contains('Delete')
.click() .click()
cy.url() cy.url()
@ -97,15 +95,15 @@ describe('Projects', () => {
cy.get('.global-notification') cy.get('.global-notification')
.should('contain', 'Success') .should('contain', 'Success')
cy.get('.namespace-container .menu.namespaces-lists .menu-list') cy.get('.menu-container .menu-list')
.should('not.contain', projects[0].title) .should('not.contain', projects[0].title)
cy.location('pathname') cy.location('pathname')
.should('equal', '/') .should('equal', '/')
}) })
it('Should archive a project', () => { it('Should archive a project', () => {
cy.visit(`/projects/${projects[0].id}`) cy.visit(`/projects/${projects[0].id}`)
cy.get('.project-title-dropdown') cy.get('.project-title-dropdown')
.click() .click()
cy.get('.project-title-dropdown .dropdown-menu .dropdown-item') cy.get('.project-title-dropdown .dropdown-menu .dropdown-item')
@ -115,10 +113,59 @@ describe('Projects', () => {
.should('contain.text', 'Archive this project') .should('contain.text', 'Archive this project')
cy.get('.modal-content [data-cy=modalPrimary]') cy.get('.modal-content [data-cy=modalPrimary]')
.click() .click()
cy.get('.namespace-container .menu.namespaces-lists .menu-list') cy.get('.menu-container .menu-list')
.should('not.contain', projects[0].title) .should('not.contain', projects[0].title)
cy.get('main.app-content') cy.get('main.app-content')
.should('contain.text', 'This project is archived. It is not possible to create new or edit tasks for it.') .should('contain.text', 'This project is archived. It is not possible to create new or edit tasks for it.')
}) })
it('Should show all projects on the projects page', () => {
const projects = ProjectFactory.create(10)
cy.visit('/projects')
projects.forEach(p => {
cy.get('[data-cy="projects-list"]')
.should('contain', p.title)
})
})
it('Should not show archived projects if the filter is not checked', () => {
ProjectFactory.create(1, {
id: 2,
}, false)
ProjectFactory.create(1, {
id: 3,
is_archived: true,
}, false)
// Initial
cy.visit('/projects')
cy.get('.project-grid')
.should('not.contain', 'Archived')
// Show archived
cy.get('[data-cy="show-archived-check"] label span')
.should('be.visible')
.click()
cy.get('[data-cy="show-archived-check"] input')
.should('be.checked')
cy.get('.project-grid')
.should('contain', 'Archived')
// Don't show archived
cy.get('[data-cy="show-archived-check"] label span')
.should('be.visible')
.click()
cy.get('[data-cy="show-archived-check"] input')
.should('not.be.checked')
// Second time visiting after unchecking
cy.visit('/projects')
cy.get('[data-cy="show-archived-check"] input')
.should('not.be.checked')
cy.get('.project-grid')
.should('not.contain', 'Archived')
})
}) })

View File

@ -3,12 +3,10 @@ import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {ProjectFactory} from '../../factories/project' import {ProjectFactory} from '../../factories/project'
import {seed} from '../../support/seed' import {seed} from '../../support/seed'
import {TaskFactory} from '../../factories/task' import {TaskFactory} from '../../factories/task'
import {NamespaceFactory} from '../../factories/namespace'
import {BucketFactory} from '../../factories/bucket' import {BucketFactory} from '../../factories/bucket'
import {updateUserSettings} from '../../support/updateUserSettings' import {updateUserSettings} from '../../support/updateUserSettings'
function seedTasks(numberOfTasks = 50, startDueDate = new Date()) { function seedTasks(numberOfTasks = 50, startDueDate = new Date()) {
NamespaceFactory.create(1)
const project = ProjectFactory.create()[0] const project = ProjectFactory.create()[0]
BucketFactory.create(1, { BucketFactory.create(1, {
project_id: project.id, project_id: project.id,
@ -137,8 +135,7 @@ describe('Home Page Task Overview', () => {
cy.visit('/') cy.visit('/')
cy.get('.home.app-content .content') cy.get('.home.app-content .content')
.should('contain.text', 'You can create a new project for your new tasks:') .should('contain.text', 'Import your projects and tasks from other services into Vikunja:')
.should('contain.text', 'Or import your projects and tasks from other services into Vikunja:')
}) })
it('Should not show the cta buttons for new project when there are tasks', () => { it('Should not show the cta buttons for new project when there are tasks', () => {

View File

@ -4,7 +4,6 @@ import {TaskFactory} from '../../factories/task'
import {ProjectFactory} from '../../factories/project' import {ProjectFactory} from '../../factories/project'
import {TaskCommentFactory} from '../../factories/task_comment' import {TaskCommentFactory} from '../../factories/task_comment'
import {UserFactory} from '../../factories/user' import {UserFactory} from '../../factories/user'
import {NamespaceFactory} from '../../factories/namespace'
import {UserProjectFactory} from '../../factories/users_project' import {UserProjectFactory} from '../../factories/users_project'
import {TaskAssigneeFactory} from '../../factories/task_assignee' import {TaskAssigneeFactory} from '../../factories/task_assignee'
import {LabelFactory} from '../../factories/labels' import {LabelFactory} from '../../factories/labels'
@ -47,13 +46,11 @@ function uploadAttachmentAndVerify(taskId: number) {
describe('Task', () => { describe('Task', () => {
createFakeUserAndLogin() createFakeUserAndLogin()
let namespaces
let projects let projects
let buckets let buckets
beforeEach(() => { beforeEach(() => {
// UserFactory.create(1) // UserFactory.create(1)
namespaces = NamespaceFactory.create(1)
projects = ProjectFactory.create(1) projects = ProjectFactory.create(1)
buckets = BucketFactory.create(1, { buckets = BucketFactory.create(1, {
project_id: projects[0].id, project_id: projects[0].id,
@ -110,7 +107,7 @@ describe('Task', () => {
cy.get('.tasks .task .favorite') cy.get('.tasks .task .favorite')
.first() .first()
.click() .click()
cy.get('.menu.namespaces-lists') cy.get('.menu-container')
.should('contain', 'Favorites') .should('contain', 'Favorites')
}) })
@ -133,7 +130,6 @@ describe('Task', () => {
cy.get('.task-view h1.title.task-id') cy.get('.task-view h1.title.task-id')
.should('contain', '#1') .should('contain', '#1')
cy.get('.task-view h6.subtitle') cy.get('.task-view h6.subtitle')
.should('contain', namespaces[0].title)
.should('contain', projects[0].title) .should('contain', projects[0].title)
cy.get('.task-view .details.content.description') cy.get('.task-view .details.content.description')
.should('contain', tasks[0].description) .should('contain', tasks[0].description)
@ -260,7 +256,6 @@ describe('Task', () => {
.click() .click()
cy.get('.task-view h6.subtitle') cy.get('.task-view h6.subtitle')
.should('contain', namespaces[0].title)
.should('contain', projects[1].title) .should('contain', projects[1].title)
cy.get('.global-notification') cy.get('.global-notification')
.should('contain', 'Success') .should('contain', 'Success')

View File

@ -1,5 +1,5 @@
{ {
"extends": "@vue/tsconfig/tsconfig.web.json", "extends": "@vue/tsconfig/tsconfig.dom.json",
"include": ["./**/*", "../support/**/*", "../factories/**/*"], "include": ["./**/*", "../support/**/*", "../factories/**/*"],
"compilerOptions": { "compilerOptions": {
"baseUrl": ".", "baseUrl": ".",

View File

@ -1,18 +0,0 @@
import {faker} from '@faker-js/faker'
import {Factory} from '../support/factory'
export class NamespaceFactory extends Factory {
static table = 'namespaces'
static factory() {
const now = new Date()
return {
id: '{increment}',
title: faker.lorem.words(3),
owner_id: 1,
created: now.toISOString(),
updated: now.toISOString(),
}
}
}

View File

@ -11,7 +11,6 @@ export class ProjectFactory extends Factory {
id: '{increment}', id: '{increment}',
title: faker.lorem.words(3), title: faker.lorem.words(3),
owner_id: 1, owner_id: 1,
namespace_id: 1,
created: now.toISOString(), created: now.toISOString(),
updated: now.toISOString(), updated: now.toISOString(),
} }

1
docker/injector.sh Normal file → Executable file
View File

@ -11,5 +11,6 @@ VIKUNJA_SENTRY_DSN="$(echo "$VIKUNJA_SENTRY_DSN" | sed -r 's/([:;])/\\\1/g')"
sed -ri "s:^(\s*window.API_URL\s*=)\s*.+:\1 '${VIKUNJA_API_URL}':g" /usr/share/nginx/html/index.html sed -ri "s:^(\s*window.API_URL\s*=)\s*.+:\1 '${VIKUNJA_API_URL}':g" /usr/share/nginx/html/index.html
sed -ri "s:^(\s*window.SENTRY_ENABLED\s*=)\s*.+:\1 ${VIKUNJA_SENTRY_ENABLED}:g" /usr/share/nginx/html/index.html sed -ri "s:^(\s*window.SENTRY_ENABLED\s*=)\s*.+:\1 ${VIKUNJA_SENTRY_ENABLED}:g" /usr/share/nginx/html/index.html
sed -ri "s:^(\s*window.SENTRY_DSN\s*=)\s*.+:\1 '${VIKUNJA_SENTRY_DSN}':g" /usr/share/nginx/html/index.html sed -ri "s:^(\s*window.SENTRY_DSN\s*=)\s*.+:\1 '${VIKUNJA_SENTRY_DSN}':g" /usr/share/nginx/html/index.html
sed -ri "s:^(\s*window.PROJECT_INFINITE_NESTING_ENABLED\s*=)\s*.+:\1 '${VIKUNJA_PROJECT_INFINITE_NESTING_ENABLED}':g" /usr/share/nginx/html/index.html
date -uIseconds | xargs echo 'info: started at' date -uIseconds | xargs echo 'info: started at'

0
docker/ipv6-disable.sh Normal file → Executable file
View File

View File

@ -4,7 +4,6 @@
pid /tmp/nginx.pid; pid /tmp/nginx.pid;
worker_processes auto; worker_processes auto;
worker_rlimit_nofile 65535;
events { events {
multi_accept on; multi_accept on;

View File

@ -2,11 +2,11 @@
"nodes": { "nodes": {
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1680030621, "lastModified": 1685498995,
"narHash": "sha256-qQa1NeS5Rvk2lgK5lSk986PC6I72yIHejzM8PFu+dHs=", "narHash": "sha256-rdyjnkq87tJp+T2Bm1OD/9NXKSsh/vLlPeqCc/mm7qs=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "402cc3633cc60dfc50378197305c984518b30773", "rev": "9cfaa8a1a00830d17487cb60a19bb86f96f09b27",
"type": "github" "type": "github"
}, },
"original": { "original": {

View File

@ -27,6 +27,9 @@
// our sentry instance to notify us of potential problems. // our sentry instance to notify us of potential problems.
window.SENTRY_ENABLED = false window.SENTRY_ENABLED = false
window.SENTRY_DSN = 'https://85694a2d757547cbbc90cd4b55c5a18d@o1047380.ingest.sentry.io/6024480' window.SENTRY_DSN = 'https://85694a2d757547cbbc90cd4b55c5a18d@o1047380.ingest.sentry.io/6024480'
// If enabled, allows the user to nest projects infinitely, instead of the default 2 levels.
// This setting might change in the future or be removed completely.
window.PROJECT_INFINITE_NESTING_ENABLED = false
</script> </script>
</body> </body>
</html> </html>

View File

@ -13,7 +13,7 @@
}, },
"homepage": "https://vikunja.io/", "homepage": "https://vikunja.io/",
"funding": "https://opencollective.com/vikunja", "funding": "https://opencollective.com/vikunja",
"packageManager": "pnpm@8.3.1", "packageManager": "pnpm@8.6.0",
"keywords": [ "keywords": [
"todo", "todo",
"productivity", "productivity",
@ -51,96 +51,96 @@
"@fortawesome/vue-fontawesome": "3.0.3", "@fortawesome/vue-fontawesome": "3.0.3",
"@github/hotkey": "2.0.1", "@github/hotkey": "2.0.1",
"@infectoone/vue-ganttastic": "2.1.4", "@infectoone/vue-ganttastic": "2.1.4",
"@intlify/unplugin-vue-i18n": "0.10.0", "@intlify/unplugin-vue-i18n": "0.11.0",
"@kyvg/vue3-notification": "2.9.0", "@kyvg/vue3-notification": "2.9.1",
"@sentry/tracing": "7.49.0", "@sentry/tracing": "7.53.1",
"@sentry/vue": "7.49.0", "@sentry/vue": "7.53.1",
"@vueuse/core": "10.1.0", "@vueuse/core": "10.1.2",
"axios": "1.3.6", "axios": "1.4.0",
"blurhash": "2.0.5", "blurhash": "2.0.5",
"bulma-css-variables": "0.9.33", "bulma-css-variables": "0.9.33",
"camel-case": "4.1.2", "camel-case": "4.1.2",
"codemirror": "5.65.12", "codemirror": "5.65.13",
"date-fns": "2.29.3", "date-fns": "2.30.0",
"dayjs": "1.11.7", "dayjs": "1.11.7",
"dompurify": "3.0.2", "dompurify": "3.0.3",
"easymde": "2.18.0", "easymde": "2.18.0",
"fast-deep-equal": "3.1.3", "fast-deep-equal": "3.1.3",
"flatpickr": "4.6.13", "flatpickr": "4.6.13",
"flexsearch": "0.7.31", "flexsearch": "0.7.31",
"floating-vue": "2.0.0-beta.20", "floating-vue": "2.0.0-beta.20",
"highlight.js": "11.7.0", "highlight.js": "11.8.0",
"is-touch-device": "1.0.1", "is-touch-device": "1.0.1",
"klona": "2.0.6", "klona": "2.0.6",
"lodash.debounce": "4.0.8", "lodash.debounce": "4.0.8",
"marked": "4.3.0", "marked": "5.0.4",
"pinia": "2.0.35", "pinia": "2.0.36",
"register-service-worker": "1.7.2", "register-service-worker": "1.7.2",
"snake-case": "3.0.4", "snake-case": "3.0.4",
"sortablejs": "1.15.0", "sortablejs": "1.15.0",
"ufo": "1.1.1", "ufo": "1.1.2",
"vue": "3.2.47", "vue": "3.2.47",
"vue-advanced-cropper": "2.8.8", "vue-advanced-cropper": "2.8.8",
"vue-flatpickr-component": "11.0.3", "vue-flatpickr-component": "11.0.3",
"vue-i18n": "9.2.2", "vue-i18n": "9.2.2",
"vue-router": "4.1.6", "vue-router": "4.2.2",
"workbox-precaching": "6.5.4", "workbox-precaching": "6.6.1",
"zhyswan-vuedraggable": "4.1.3" "zhyswan-vuedraggable": "4.1.3"
}, },
"devDependencies": { "devDependencies": {
"@4tw/cypress-drag-drop": "2.2.3", "@4tw/cypress-drag-drop": "2.2.3",
"@cypress/vite-dev-server": "5.0.5", "@cypress/vite-dev-server": "5.0.5",
"@cypress/vue": "5.0.5", "@cypress/vue": "5.0.5",
"@faker-js/faker": "7.6.0", "@faker-js/faker": "8.0.2",
"@histoire/plugin-screenshot": "0.16.1", "@histoire/plugin-screenshot": "0.16.1",
"@histoire/plugin-vue": "0.16.1", "@histoire/plugin-vue": "0.16.1",
"@rushstack/eslint-patch": "1.2.0", "@rushstack/eslint-patch": "1.3.0",
"@tsconfig/node18": "2.0.1",
"@types/codemirror": "5.60.7", "@types/codemirror": "5.60.7",
"@types/dompurify": "3.0.2", "@types/dompurify": "3.0.2",
"@types/flexsearch": "0.7.3", "@types/flexsearch": "0.7.3",
"@types/is-touch-device": "1.0.0", "@types/is-touch-device": "1.0.0",
"@types/lodash.debounce": "4.0.7", "@types/lodash.debounce": "4.0.7",
"@types/marked": "4.0.8", "@types/marked": "5.0.0",
"@types/node": "18.16.1", "@types/node": "18.16.16",
"@types/postcss-preset-env": "7.7.0", "@types/postcss-preset-env": "7.7.0",
"@types/sortablejs": "1.15.1", "@types/sortablejs": "1.15.1",
"@typescript-eslint/eslint-plugin": "5.59.1", "@typescript-eslint/eslint-plugin": "5.59.8",
"@typescript-eslint/parser": "5.59.1", "@typescript-eslint/parser": "5.59.8",
"@vitejs/plugin-legacy": "4.0.3", "@vitejs/plugin-legacy": "4.0.4",
"@vitejs/plugin-vue": "4.2.0", "@vitejs/plugin-vue": "4.2.3",
"@vue/eslint-config-typescript": "11.0.3", "@vue/eslint-config-typescript": "11.0.3",
"@vue/test-utils": "2.3.2", "@vue/test-utils": "2.3.2",
"@vue/tsconfig": "0.1.3", "@vue/tsconfig": "0.4.0",
"autoprefixer": "10.4.14", "autoprefixer": "10.4.14",
"browserslist": "4.21.5", "browserslist": "4.21.5",
"caniuse-lite": "1.0.30001481", "caniuse-lite": "1.0.30001489",
"css-has-pseudo": "5.0.2", "css-has-pseudo": "5.0.2",
"csstype": "3.1.2", "csstype": "3.1.2",
"cypress": "12.10.0", "cypress": "12.13.0",
"esbuild": "0.17.18", "esbuild": "0.17.19",
"eslint": "8.39.0", "eslint": "8.41.0",
"eslint-plugin-vue": "9.11.0", "eslint-plugin-vue": "9.13.0",
"happy-dom": "9.9.2", "happy-dom": "9.20.1",
"histoire": "0.16.1", "histoire": "0.16.1",
"netlify-cli": "14.2.1", "postcss": "8.4.24",
"postcss": "8.4.23",
"postcss-easing-gradients": "3.0.1", "postcss-easing-gradients": "3.0.1",
"postcss-easings": "3.0.1", "postcss-easings": "3.0.1",
"postcss-focus-within": "7.0.2", "postcss-focus-within": "7.0.2",
"postcss-preset-env": "8.3.2", "postcss-preset-env": "8.4.1",
"rollup": "3.21.0", "rollup": "3.23.0",
"rollup-plugin-visualizer": "5.9.0", "rollup-plugin-visualizer": "5.9.0",
"sass": "1.62.1", "sass": "1.62.1",
"start-server-and-test": "2.0.0", "start-server-and-test": "2.0.0",
"typescript": "5.0.4", "typescript": "5.0.4",
"vite": "4.3.3", "vite": "4.3.9",
"vite-plugin-inject-preload": "1.3.1", "vite-plugin-inject-preload": "1.3.1",
"vite-plugin-pwa": "0.14.7", "vite-plugin-pwa": "0.15.2",
"vite-svg-loader": "4.0.0", "vite-svg-loader": "4.0.0",
"vitest": "0.30.1", "vitest": "0.31.2",
"vue-tsc": "1.4.4", "vue-tsc": "1.6.5",
"wait-on": "7.0.1", "wait-on": "7.0.1",
"workbox-cli": "6.5.4" "workbox-cli": "6.6.1"
}, },
"pnpm": { "pnpm": {
"patchedDependencies": { "patchedDependencies": {

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,7 @@
], ],
"packageRules": [ "packageRules": [
{ {
"matchPackageNames": ["netlify-cli", "happy-dom"], "matchPackageNames": ["happy-dom"],
"extends": ["schedule:weekly"] "extends": ["schedule:weekly"]
}, },
{ {

View File

@ -33,9 +33,9 @@ const promiseExec = cmd => {
} }
(async function () { (async function () {
let stdout = await promiseExec(`./node_modules/.bin/netlify link --id ${siteId}`) let stdout = await promiseExec(`/home/node/docker-netlify-cli/node_modules/.bin/netlify link --id ${siteId}`)
console.log(stdout) console.log(stdout)
stdout = await promiseExec(`./node_modules/.bin/netlify deploy --alias ${alias}`) stdout = await promiseExec(`/home/node/docker-netlify-cli/node_modules/.bin/netlify deploy --alias ${alias}`)
console.log(stdout) console.log(stdout)
const data = await fetch(prIssueCommentsUrl).then(response => response.json()) const data = await fetch(prIssueCommentsUrl).then(response => response.json())

View File

@ -1 +1 @@
57af69409e66bc87f4f2fc5822dd8d3c2eb47c601f81af1ac4a56f3e2d80837b1a2de06f4ff57695ec379b7c15b881e3 ./scripts/deploy-preview-netlify.mjs 4a7c1293c7b12e9ab476cdf35251a407c6a1cd005d22c06df994222cccfb25cde5f47d15866a098c9d739778fee4dc19 ./scripts/deploy-preview-netlify.mjs

View File

@ -0,0 +1,107 @@
<template>
<draggable
v-model="availableProjects"
animation="100"
ghostClass="ghost"
group="projects"
@start="() => drag = true"
@end="saveProjectPosition"
handle=".handle"
tag="menu"
item-key="id"
:disabled="!canEditOrder"
:component-data="{
type: 'transition-group',
name: !drag ? 'flip-list' : null,
class: [
'menu-list can-be-hidden',
{ 'dragging-disabled': !canEditOrder }
]
}"
>
<template #item="{element: project}">
<ProjectsNavigationItem
:project="project"
:is-loading="projectUpdating[project.id]"
:can-collapse="canCollapse"
:level="level"
:data-project-id="project.id"
/>
</template>
</draggable>
</template>
<script lang="ts" setup>
import {ref, watch} from 'vue'
import draggable from 'zhyswan-vuedraggable'
import type {SortableEvent} from 'sortablejs'
import ProjectsNavigationItem from '@/components/home/ProjectsNavigationItem.vue'
import {calculateItemPosition} from '@/helpers/calculateItemPosition'
import type {IProject} from '@/modelTypes/IProject'
import {useProjectStore} from '@/stores/projects'
const props = defineProps<{
modelValue?: IProject[],
canEditOrder: boolean,
canCollapse?: boolean,
level?: number,
}>()
const emit = defineEmits<{
(e: 'update:modelValue', projects: IProject[]): void
}>()
const drag = ref(false)
const projectStore = useProjectStore()
// Vue draggable will modify the projects list as it changes their position which will not work on a prop.
// Hence, we'll clone the prop and work on the clone.
const availableProjects = ref<IProject[]>([])
watch(
() => props.modelValue,
projects => {
availableProjects.value = projects || []
},
{immediate: true},
)
const projectUpdating = ref<{ [id: IProject['id']]: boolean }>({})
async function saveProjectPosition(e: SortableEvent) {
if (!e.newIndex && e.newIndex !== 0) return
const projectsActive = availableProjects.value
// If the project was dragged to the last position, Safari will report e.newIndex as the size of the projectsActive
// array instead of using the position. Because the index is wrong in that case, dragging the project will fail.
// To work around that we're explicitly checking that case here and decrease the index.
const newIndex = e.newIndex === projectsActive.length ? e.newIndex - 1 : e.newIndex
const projectId = parseInt(e.item.dataset.projectId)
const project = projectStore.projects[projectId]
const parentProjectId = e.to.parentNode.dataset.projectId ? parseInt(e.to.parentNode.dataset.projectId) : 0
const projectBefore = projectsActive[newIndex - 1] ?? null
const projectAfter = projectsActive[newIndex + 1] ?? null
projectUpdating.value[project.id] = true
const position = calculateItemPosition(
projectBefore !== null ? projectBefore.position : null,
projectAfter !== null ? projectAfter.position : null,
)
try {
// create a copy of the project in order to not violate pinia manipulation
await projectStore.updateProject({
...project,
position,
parentProjectId,
})
emit('update:modelValue', availableProjects.value)
} finally {
projectUpdating.value[project.id] = false
}
}
</script>

View File

@ -0,0 +1,156 @@
<template>
<li
class="list-menu loader-container is-loading-small"
:class="{'is-loading': isLoading}"
>
<div>
<BaseButton
v-if="canCollapse && childProjects?.length > 0"
@click="childProjectsOpen = !childProjectsOpen"
class="collapse-project-button"
>
<icon icon="chevron-down" :class="{ 'project-is-collapsed': !childProjectsOpen }"/>
</BaseButton>
<BaseButton
:to="{ name: 'project.index', params: { projectId: project.id} }"
class="list-menu-link"
:class="{'router-link-exact-active': currentProject?.id === project.id}"
>
<span
v-if="!canCollapse || childProjects?.length === 0"
class="collapse-project-button-placeholder"
></span>
<div class="color-bubble-handle-wrapper">
<ColorBubble
v-if="project.hexColor !== ''"
:color="project.hexColor"
/>
<span
class="icon menu-item-icon handle lines-handle"
:class="{'has-color-bubble': project.hexColor !== ''}"
>
<icon icon="grip-lines"/>
</span>
</div>
<span class="list-menu-title">{{ getProjectTitle(project) }}</span>
</BaseButton>
<BaseButton
v-if="project.id > 0"
class="favorite"
:class="{'is-favorite': project.isFavorite}"
@click="projectStore.toggleProjectFavorite(project)"
>
<icon :icon="project.isFavorite ? 'star' : ['far', 'star']"/>
</BaseButton>
<ProjectSettingsDropdown
v-if="project.id > 0"
class="menu-list-dropdown"
:project="project"
:level="level"
>
<template #trigger="{toggleOpen}">
<BaseButton class="menu-list-dropdown-trigger" @click="toggleOpen">
<icon icon="ellipsis-h" class="icon"/>
</BaseButton>
</template>
</ProjectSettingsDropdown>
<span class="list-setting-spacer" v-else></span>
</div>
<ProjectsNavigation
v-if="canNestDeeper && childProjectsOpen && canCollapse"
:model-value="childProjects"
:can-edit-order="true"
:can-collapse="canCollapse"
:level="level + 1"
/>
</li>
</template>
<script setup lang="ts">
import {computed, ref} from 'vue'
import {useProjectStore} from '@/stores/projects'
import {useBaseStore} from '@/stores/base'
import type {IProject} from '@/modelTypes/IProject'
import BaseButton from '@/components/base/BaseButton.vue'
import ProjectSettingsDropdown from '@/components/project/project-settings-dropdown.vue'
import {getProjectTitle} from '@/helpers/getProjectTitle'
import ColorBubble from '@/components/misc/colorBubble.vue'
import ProjectsNavigation from '@/components/home/ProjectsNavigation.vue'
import {canNestProjectDeeper} from '@/helpers/canNestProjectDeeper'
const props = withDefaults(defineProps<{
project: IProject,
isLoading?: boolean,
canCollapse?: boolean,
level?: number,
}>(), {
level: 0,
})
const projectStore = useProjectStore()
const baseStore = useBaseStore()
const currentProject = computed(() => baseStore.currentProject)
const childProjectsOpen = ref(true)
const childProjects = computed(() => {
if (!canNestDeeper.value) {
return []
}
return projectStore.getChildProjects(props.project.id)
.sort((a, b) => a.position - b.position)
})
const canNestDeeper = computed(() => canNestProjectDeeper(props.level))
</script>
<style lang="scss" scoped>
.list-setting-spacer {
width: 5rem;
flex-shrink: 0;
}
.project-is-collapsed {
transform: rotate(-90deg);
}
.favorite {
transition: opacity $transition, color $transition;
opacity: 0;
&:hover,
&.is-favorite {
opacity: 1;
color: var(--warning);
}
}
.list-menu:hover > div > .favorite {
opacity: 1;
}
.list-menu:hover > div > a > .color-bubble-handle-wrapper > .color-bubble {
opacity: 0;
}
.color-bubble-handle-wrapper {
position: relative;
width: 1rem;
height: 1rem;
display: flex;
align-items: center;
justify-content: flex-start;
margin-right: .25rem;
.color-bubble, .icon {
transition: all $transition;
position: absolute;
width: 12px;
margin: 0 !important;
padding: 0 !important;
}
}
</style>

View File

@ -7,8 +7,9 @@
<MenuButton class="menu-button" /> <MenuButton class="menu-button" />
<div v-if="currentProject.id" class="project-title-wrapper"> <div v-if="currentProject?.id" class="project-title-wrapper">
<h1 class="project-title">{{ currentProject.title === '' ? $t('misc.loading') : getProjectTitle(currentProject) }} <h1 class="project-title">
{{ currentProject.title === '' ? $t('misc.loading') : getProjectTitle(currentProject) }}
</h1> </h1>
<BaseButton :to="{ name: 'project.info', params: { projectId: currentProject.id } }" class="project-title-button"> <BaseButton :to="{ name: 'project.info', params: { projectId: currentProject.id } }" class="project-title-button">
@ -89,7 +90,7 @@ import { useAuthStore } from '@/stores/auth'
const baseStore = useBaseStore() const baseStore = useBaseStore()
const currentProject = computed(() => baseStore.currentProject) const currentProject = computed(() => baseStore.currentProject)
const background = computed(() => baseStore.background) const background = computed(() => baseStore.background)
const canWriteCurrentProject = computed(() => baseStore.currentProject.maxRight > Rights.READ) const canWriteCurrentProject = computed(() => baseStore.currentProject?.maxRight > Rights.READ)
const menuActive = computed(() => baseStore.menuActive) const menuActive = computed(() => baseStore.menuActive)
const authStore = useAuthStore() const authStore = useAuthStore()

View File

@ -69,6 +69,7 @@ import BaseButton from '@/components/base/BaseButton.vue'
import {useBaseStore} from '@/stores/base' import {useBaseStore} from '@/stores/base'
import {useLabelStore} from '@/stores/labels' import {useLabelStore} from '@/stores/labels'
import {useProjectStore} from '@/stores/projects'
import {useRouteWithModal} from '@/composables/useRouteWithModal' import {useRouteWithModal} from '@/composables/useRouteWithModal'
import {useRenewTokenOnFocus} from '@/composables/useRenewTokenOnFocus' import {useRenewTokenOnFocus} from '@/composables/useRenewTokenOnFocus'
@ -94,14 +95,13 @@ watch(() => route.name as string, (routeName) => {
( (
[ [
'home', 'home',
'namespace.edit',
'teams.index', 'teams.index',
'teams.edit', 'teams.edit',
'tasks.range', 'tasks.range',
'labels.index', 'labels.index',
'migrate.start', 'migrate.start',
'migrate.wunderlist', 'migrate.wunderlist',
'namespaces.index', 'projects.index',
].includes(routeName) || ].includes(routeName) ||
routeName.startsWith('user.settings') routeName.startsWith('user.settings')
) )
@ -116,6 +116,9 @@ useRenewTokenOnFocus()
const labelStore = useLabelStore() const labelStore = useLabelStore()
labelStore.loadAllLabels() labelStore.loadAllLabels()
const projectStore = useProjectStore()
projectStore.loadProjects()
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -9,9 +9,9 @@
<Logo class="logo" v-if="logoVisible"/> <Logo class="logo" v-if="logoVisible"/>
<h1 <h1
:class="{'m-0': !logoVisible}" :class="{'m-0': !logoVisible}"
:style="{ 'opacity': currentProject.title === '' ? '0': '1' }" :style="{ 'opacity': currentProject?.title === '' ? '0': '1' }"
class="title"> class="title">
{{ currentProject.title === '' ? $t('misc.loading') : currentProject.title }} {{ currentProject?.title === '' ? $t('misc.loading') : currentProject?.title }}
</h1> </h1>
<div class="box has-text-left view"> <div class="box has-text-left view">
<router-view/> <router-view/>

View File

@ -1,10 +1,10 @@
<template> <template>
<aside :class="{'is-active': menuActive}" class="namespace-container"> <aside :class="{'is-active': baseStore.menuActive}" class="menu-container">
<nav class="menu top-menu"> <nav class="menu top-menu">
<router-link :to="{name: 'home'}" class="logo"> <router-link :to="{name: 'home'}" class="logo">
<Logo width="164" height="48"/> <Logo width="164" height="48"/>
</router-link> </router-link>
<ul class="menu-list"> <menu class="menu-list other-menu-items">
<li> <li>
<router-link :to="{ name: 'home'}" v-shortcut="'g o'"> <router-link :to="{ name: 'home'}" v-shortcut="'g o'">
<span class="menu-item-icon icon"> <span class="menu-item-icon icon">
@ -22,11 +22,11 @@
</router-link> </router-link>
</li> </li>
<li> <li>
<router-link :to="{ name: 'namespaces.index'}" v-shortcut="'g n'"> <router-link :to="{ name: 'projects.index'}" v-shortcut="'g p'">
<span class="menu-item-icon icon"> <span class="menu-item-icon icon">
<icon icon="layer-group"/> <icon icon="layer-group"/>
</span> </span>
{{ $t('namespace.title') }} {{ $t('project.projects') }}
</router-link> </router-link>
</li> </li>
<li> <li>
@ -45,238 +45,51 @@
{{ $t('team.title') }} {{ $t('team.title') }}
</router-link> </router-link>
</li> </li>
</ul> </menu>
</nav> </nav>
<nav class="menu namespaces-lists loader-container is-loading-small" :class="{'is-loading': loading}"> <Loading
<template v-for="(n, nk) in namespaces" :key="n.id"> v-if="projectStore.isLoading"
<div class="namespace-title" :class="{'has-menu': n.id > 0}"> variant="small"
<BaseButton />
@click="toggleProjects(n.id)" <template v-else>
class="menu-label" <nav class="menu" v-if="favoriteProjects">
v-tooltip="namespaceTitles[nk]" <ProjectsNavigation :model-value="favoriteProjects" :can-edit-order="false" :can-collapse="false"/>
> </nav>
<ColorBubble
v-if="n.hexColor !== ''" <nav class="menu">
:color="n.hexColor" <ProjectsNavigation
class="mr-1" :model-value="projects"
/> :can-edit-order="true"
<span class="name">{{ namespaceTitles[nk] }}</span> :can-collapse="true"
<div :level="1"
class="icon menu-item-icon is-small toggle-lists-icon pl-2" />
:class="{'active': typeof projectsVisible[n.id] !== 'undefined' ? projectsVisible[n.id] : true}" </nav>
> </template>
<icon icon="chevron-down"/>
</div>
<span class="count" :class="{'ml-2 mr-0': n.id > 0}">
({{ namespaceProjectsCount[nk] }})
</span>
</BaseButton>
<namespace-settings-dropdown class="menu-list-dropdown" :namespace="n" v-if="n.id > 0"/>
</div>
<!--
NOTE: a v-model / computed setter is not possible, since the updateActiveProjects function
triggered by the change needs to have access to the current namespace
-->
<draggable
v-if="projectsVisible[n.id] ?? true"
v-bind="dragOptions"
:modelValue="activeProjects[nk]"
@update:modelValue="(projects) => updateActiveProjects(n, projects)"
group="namespace-lists"
@start="() => drag = true"
@end="saveListPosition"
handle=".handle"
:disabled="n.id < 0 || undefined"
tag="ul"
item-key="id"
:data-namespace-id="n.id"
:data-namespace-index="nk"
:component-data="{
type: 'transition-group',
name: !drag ? 'flip-list' : null,
class: [
'menu-list can-be-hidden',
{ 'dragging-disabled': n.id < 0 }
]
}"
>
<template #item="{element: l}">
<li
class="list-menu loader-container is-loading-small"
:class="{'is-loading': projectUpdating[l.id]}"
>
<BaseButton
:to="{ name: 'project.index', params: { projectId: l.id} }"
class="list-menu-link"
:class="{'router-link-exact-active': currentProject.id === l.id}"
>
<span class="icon menu-item-icon handle">
<icon icon="grip-lines"/>
</span>
<ColorBubble
v-if="l.hexColor !== ''"
:color="l.hexColor"
class="mr-1"
/>
<span class="list-menu-title">{{ getProjectTitle(l) }}</span>
</BaseButton>
<BaseButton
v-if="l.id > 0"
class="favorite"
:class="{'is-favorite': l.isFavorite}"
@click="projectStore.toggleProjectFavorite(l)"
>
<icon :icon="l.isFavorite ? 'star' : ['far', 'star']"/>
</BaseButton>
<ProjectSettingsDropdown class="menu-list-dropdown" :project="l" v-if="l.id > 0">
<template #trigger="{toggleOpen}">
<BaseButton class="menu-list-dropdown-trigger" @click="toggleOpen">
<icon icon="ellipsis-h" class="icon"/>
</BaseButton>
</template>
</ProjectSettingsDropdown>
<span class="list-setting-spacer" v-else></span>
</li>
</template>
</draggable>
</template>
</nav>
<PoweredByLink/> <PoweredByLink/>
</aside> </aside>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import {ref, computed, onBeforeMount} from 'vue' import {computed} from 'vue'
import draggable from 'zhyswan-vuedraggable'
import type {SortableEvent} from 'sortablejs'
import BaseButton from '@/components/base/BaseButton.vue'
import ProjectSettingsDropdown from '@/components/project/project-settings-dropdown.vue'
import NamespaceSettingsDropdown from '@/components/namespace/namespace-settings-dropdown.vue'
import PoweredByLink from '@/components/home/PoweredByLink.vue' import PoweredByLink from '@/components/home/PoweredByLink.vue'
import Logo from '@/components/home/Logo.vue' import Logo from '@/components/home/Logo.vue'
import Loading from '@/components/misc/loading.vue'
import {calculateItemPosition} from '@/helpers/calculateItemPosition'
import {getNamespaceTitle} from '@/helpers/getNamespaceTitle'
import {getProjectTitle} from '@/helpers/getProjectTitle'
import type {IProject} from '@/modelTypes/IProject'
import type {INamespace} from '@/modelTypes/INamespace'
import ColorBubble from '@/components/misc/colorBubble.vue'
import {useBaseStore} from '@/stores/base' import {useBaseStore} from '@/stores/base'
import {useProjectStore} from '@/stores/projects' import {useProjectStore} from '@/stores/projects'
import {useNamespaceStore} from '@/stores/namespaces' import ProjectsNavigation from '@/components/home/ProjectsNavigation.vue'
const drag = ref(false)
const dragOptions = {
animation: 100,
ghostClass: 'ghost',
}
const baseStore = useBaseStore() const baseStore = useBaseStore()
const namespaceStore = useNamespaceStore()
const currentProject = computed(() => baseStore.currentProject)
const menuActive = computed(() => baseStore.menuActive)
const loading = computed(() => namespaceStore.isLoading)
const namespaces = computed(() => {
return namespaceStore.namespaces.filter(n => !n.isArchived)
})
const activeProjects = computed(() => {
return namespaces.value.map(({projects}) => {
return projects?.filter(item => {
return typeof item !== 'undefined' && !item.isArchived
})
})
})
const namespaceTitles = computed(() => {
return namespaces.value.map((namespace) => getNamespaceTitle(namespace))
})
const namespaceProjectsCount = computed(() => {
return namespaces.value.map((_, index) => activeProjects.value[index]?.length ?? 0)
})
const projectStore = useProjectStore() const projectStore = useProjectStore()
function toggleProjects(namespaceId: INamespace['id']) { const projects = computed(() => projectStore.notArchivedRootProjects)
projectsVisible.value[namespaceId] = !projectsVisible.value[namespaceId] const favoriteProjects = computed(() => projectStore.favoriteProjects)
}
const projectsVisible = ref<{ [id: INamespace['id']]: boolean }>({})
// FIXME: async action will be unfinished when component mounts
onBeforeMount(async () => {
const namespaces = await namespaceStore.loadNamespaces()
namespaces.forEach(n => {
if (typeof projectsVisible.value[n.id] === 'undefined') {
projectsVisible.value[n.id] = true
}
})
})
function updateActiveProjects(namespace: INamespace, activeProjects: IProject[]) {
// This is a bit hacky: since we do have to filter out the archived items from the list
// for vue draggable updating it is not as simple as replacing it.
// To work around this, we merge the active projects with the archived ones. Doing so breaks the order
// because now all archived projects are sorted after the active ones. This is fine because they are sorted
// later when showing them anyway, and it makes the merging happening here a lot easier.
const projects = [
...activeProjects,
...namespace.projects.filter(l => l.isArchived),
]
namespaceStore.setNamespaceById({
...namespace,
projects,
})
}
const projectUpdating = ref<{ [id: INamespace['id']]: boolean }>({})
async function saveListPosition(e: SortableEvent) {
if (!e.newIndex && e.newIndex !== 0) return
const namespaceId = parseInt(e.to.dataset.namespaceId as string)
const newNamespaceIndex = parseInt(e.to.dataset.namespaceIndex as string)
const projectsActive = activeProjects.value[newNamespaceIndex]
// If the project was dragged to the last position, Safari will report e.newIndex as the size of the projectsActive
// array instead of using the position. Because the index is wrong in that case, dragging the project will fail.
// To work around that we're explicitly checking that case here and decrease the index.
const newIndex = e.newIndex === projectsActive.length ? e.newIndex - 1 : e.newIndex
const project = projectsActive[newIndex]
const projectBefore = projectsActive[newIndex - 1] ?? null
const projectAfter = projectsActive[newIndex + 1] ?? null
projectUpdating.value[project.id] = true
const position = calculateItemPosition(
projectBefore !== null ? projectBefore.position : null,
projectAfter !== null ? projectAfter.position : null,
)
try {
// create a copy of the project in order to not violate pinia manipulation
await projectStore.updateProject({
...project,
position,
namespaceId,
})
} finally {
projectUpdating.value[project.id] = false
}
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
$navbar-padding: 2rem;
$vikunja-nav-background: var(--site-background);
$vikunja-nav-color: var(--grey-700);
$vikunja-nav-selected-width: 0.4rem;
.logo { .logo {
display: block; display: block;
@ -289,8 +102,8 @@ $vikunja-nav-selected-width: 0.4rem;
} }
} }
.namespace-container { .menu-container {
background: $vikunja-nav-background; background: var(--site-background);
color: $vikunja-nav-color; color: $vikunja-nav-color;
padding: 0 0 1rem; padding: 0 0 1rem;
transition: transform $transition-duration ease-in; transition: transform $transition-duration ease-in;
@ -301,6 +114,7 @@ $vikunja-nav-selected-width: 0.4rem;
transform: translateX(-100%); transform: translateX(-100%);
overflow-x: auto; overflow-x: auto;
width: $navbar-width; width: $navbar-width;
margin-top: 1rem;
@media screen and (max-width: $tablet) { @media screen and (max-width: $tablet) {
top: 0; top: 0;
@ -314,252 +128,24 @@ $vikunja-nav-selected-width: 0.4rem;
} }
} }
// these are general menu styles .top-menu .menu-list {
// should be in own components li {
.menu {
.menu-label,
.menu-list .list-menu-link,
.menu-list a {
display: flex;
align-items: center;
justify-content: space-between;
cursor: pointer;
.color-bubble {
height: 12px;
flex: 0 0 12px;
}
}
.menu-list {
li {
height: 44px;
display: flex;
align-items: center;
&:hover {
background: var(--white);
}
.menu-list-dropdown {
opacity: 1;
transition: $transition;
}
@media(hover: hover) and (pointer: fine) {
.menu-list-dropdown {
opacity: 0;
}
&:hover .menu-list-dropdown {
opacity: 1;
}
}
}
.menu-item-icon {
color: var(--grey-400);
}
.menu-list-dropdown-trigger {
display: flex;
padding: 0.5rem;
}
.flip-list-move {
transition: transform $transition-duration;
}
.ghost {
background: var(--grey-200);
* {
opacity: 0;
}
}
a:hover {
background: transparent;
}
.list-menu-link,
li > a {
color: $vikunja-nav-color;
padding: 0.75rem .5rem 0.75rem ($navbar-padding * 1.5 - 1.75rem);
transition: all 0.2s ease;
border-radius: 0;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
width: 100%;
border-left: $vikunja-nav-selected-width solid transparent;
&:hover {
border-left: $vikunja-nav-selected-width solid var(--primary);
}
&.router-link-exact-active {
color: var(--primary);
border-left: $vikunja-nav-selected-width solid var(--primary);
}
.icon {
height: 1rem;
vertical-align: middle;
padding-right: 0.5rem;
}
&.router-link-exact-active .icon:not(.handle) {
color: var(--primary);
}
.handle {
opacity: 0;
transition: opacity $transition;
margin-right: .25rem;
}
&:hover .handle {
opacity: 1;
}
}
&:not(.dragging-disabled) .handle {
cursor: grab;
}
}
}
.top-menu {
margin-top: math.div($navbar-padding, 2);
.menu-list {
li {
font-weight: 600;
font-family: $vikunja-font;
}
.list-menu-link,
li > a {
padding-left: 2rem;
display: inline-block;
.icon {
padding-bottom: .25rem;
}
}
}
}
.namespaces-lists {
padding-top: math.div($navbar-padding, 2);
.menu-label {
font-size: 1rem;
font-weight: 700;
font-weight: bold;
font-family: $vikunja-font;
color: $vikunja-nav-color;
font-weight: 600; font-weight: 600;
min-height: 2.5rem; font-family: $vikunja-font;
padding-top: 0;
padding-left: $navbar-padding;
overflow: hidden;
margin-bottom: 0;
flex: 1 1 auto;
.name {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-right: auto;
}
.count {
color: var(--grey-500);
margin-right: .5rem;
// align brackets with number
font-feature-settings: "case";
}
} }
.favorite { .list-menu-link,
margin-left: .25rem; li > a {
transition: opacity $transition, color $transition; padding-left: 2rem;
opacity: 1; display: inline-block;
&.is-favorite { .icon {
color: var(--warning); padding-bottom: .25rem;
opacity: 1;
} }
} }
@media(hover: hover) and (pointer: fine) {
.list-menu .favorite {
opacity: 0;
}
.list-menu:hover .favorite,
.favorite.is-favorite {
opacity: 1;
}
}
.list-menu-title {
overflow: hidden;
text-overflow: ellipsis;
width: 100%;
}
.color-bubble {
width: 14px;
height: 14px;
flex-basis: auto;
}
.is-archived {
min-width: 85px;
}
} }
.namespace-title { .menu + .menu {
display: flex; padding-top: math.div($navbar-padding, 2);
align-items: center;
justify-content: space-between;
color: $vikunja-nav-color;
padding: 0 .25rem;
.toggle-lists-icon {
svg {
transition: all $transition;
transform: rotate(90deg);
opacity: 1;
}
&.active svg {
transform: rotate(0deg);
opacity: 0;
}
}
&:hover .toggle-lists-icon svg {
opacity: 1;
}
&:not(.has-menu) .toggle-lists-icon {
padding-right: 1rem;
}
}
.list-setting-spacer {
width: 2.5rem;
flex-shrink: 0;
}
.namespaces-list.loader-container.is-loading {
min-height: calc(100vh - #{$navbar-height + 1.5rem + 1rem + 1.5rem});
} }
</style> </style>

View File

@ -1,63 +0,0 @@
<template>
<multiselect
v-model="selectedNamespaces"
:search-results="foundNamespaces"
:loading="namespaceService.loading"
:multiple="true"
:placeholder="$t('namespace.search')"
label="namespace"
@search="findNamespaces"
/>
</template>
<script setup lang="ts">
import {computed, ref, shallowReactive, watchEffect, type PropType} from 'vue'
import Multiselect from '@/components/input/multiselect.vue'
import type {INamespace} from '@/modelTypes/INamespace'
import NamespaceService from '@/services/namespace'
import {includesById} from '@/helpers/utils'
const props = defineProps({
modelValue: {
type: Array as PropType<INamespace[]>,
default: () => [],
},
})
const emit = defineEmits<{
(e: 'update:modelValue', value: INamespace[]): void
}>()
const namespaces = ref<INamespace[]>([])
watchEffect(() => {
namespaces.value = props.modelValue
})
const selectedNamespaces = computed({
get() {
return namespaces.value
},
set: (value) => {
namespaces.value = value
emit('update:modelValue', value)
},
})
const namespaceService = shallowReactive(new NamespaceService())
const foundNamespaces = ref<INamespace[]>([])
async function findNamespaces(query: string) {
if (query === '') {
foundNamespaces.value = []
return
}
const response = await namespaceService.getAll({}, {s: query}) as INamespace[]
// Filter selected items from the results
foundNamespaces.value = response.filter(({id}) => !includesById(namespaces.value, id))
}
</script>

View File

@ -158,7 +158,12 @@ const flatPickerConfig = computed(() => ({
// Since flatpickr dates are strings, we need to convert them to native date objects. // Since flatpickr dates are strings, we need to convert them to native date objects.
// To make that work, we need a separate variable since flatpickr does not have a change event. // To make that work, we need a separate variable since flatpickr does not have a change event.
const flatPickrDate = computed({ const flatPickrDate = computed({
set(newValue: string | Date) { set(newValue: string | Date | null) {
if (newValue === null) {
date.value = null
return
}
date.value = createDateFromString(newValue) date.value = createDateFromString(newValue)
updateData() updateData()
}, },

View File

@ -211,7 +211,7 @@ function handleInput(val: string) {
bubble(1000) bubble(1000)
} }
function bubble(timeout = 500) { function bubble(timeout = 5000) {
if (changeTimeout.value !== null) { if (changeTimeout.value !== null) {
clearTimeout(changeTimeout.value) clearTimeout(changeTimeout.value)
} }

View File

@ -24,12 +24,12 @@
}" }"
> >
<div :class="{'content': hasContent}"> <div :class="{'content': hasContent}">
<slot /> <slot/>
</div> </div>
</div> </div>
<footer v-if="$slots.footer" class="card-footer"> <footer v-if="$slots.footer" class="card-footer">
<slot name="footer" /> <slot name="footer"/>
</footer> </footer>
</div> </div>
</template> </template>
@ -76,22 +76,27 @@ defineEmits(['close'])
<style lang="scss" scoped> <style lang="scss" scoped>
.card { .card {
background-color: var(--white); background-color: var(--white);
border-radius: $radius; border-radius: $radius;
margin-bottom: 1rem; margin-bottom: 1rem;
border: 1px solid var(--card-border-color); border: 1px solid var(--card-border-color);
box-shadow: var(--shadow-sm); box-shadow: var(--shadow-sm);
@media print {
box-shadow: none;
border: none;
}
} }
.card-header { .card-header {
box-shadow: none; box-shadow: none;
border-bottom: 1px solid var(--card-border-color); border-bottom: 1px solid var(--card-border-color);
border-radius: $radius $radius 0 0; border-radius: $radius $radius 0 0;
} }
.card-footer { .card-footer {
background-color: var(--grey-50); background-color: var(--grey-50);
border-top: 0; border-top: 0;
padding: var(--modal-card-head-padding); padding: var(--modal-card-head-padding);
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;

View File

@ -44,8 +44,8 @@ export const KEYBOARD_SHORTCUTS : ShortcutGroup[] = [
combination: 'then', combination: 'then',
}, },
{ {
title: 'keyboardShortcuts.navigation.namespaces', title: 'keyboardShortcuts.navigation.projects',
keys: ['g', 'n'], keys: ['g', 'p'],
combination: 'then', combination: 'then',
}, },
{ {
@ -140,6 +140,18 @@ export const KEYBOARD_SHORTCUTS : ShortcutGroup[] = [
title: 'keyboardShortcuts.task.description', title: 'keyboardShortcuts.task.description',
keys: ['e'], keys: ['e'],
}, },
{
title: 'keyboardShortcuts.task.priority',
keys: ['p'],
},
{
title: 'keyboardShortcuts.task.delete',
keys: ['shift', 'delete'],
},
{
title: 'keyboardShortcuts.task.favorite',
keys: ['s'],
},
], ],
}, },
] ]

View File

@ -1,13 +1,21 @@
<template> <template>
<div class="loader-container is-loading"></div> <div class="loader-container is-loading" :class="{'is-small': variant === 'small'}"></div>
</template> </template>
<script lang="ts"> <script lang="ts">
export default { export default {
inheritAttrs: false, inheritAttrs: true,
} }
</script> </script>
<script lang="ts" setup>
const {
variant = 'default',
} = defineProps<{
variant?: 'default' | 'small'
}>()
</script>
<style scoped lang="scss"> <style scoped lang="scss">
.loader-container { .loader-container {
height: 100%; height: 100%;
@ -20,5 +28,18 @@ export default {
min-height: 50px; min-height: 50px;
min-width: 100px; min-width: 100px;
} }
&.is-small {
min-width: 100%;
height: 150px;
&.is-loading::after {
width: 3rem;
height: 3rem;
top: calc(50% - 1.5rem);
left: calc(50% - 1.5rem);
border-width: 3px;
}
}
} }
</style> </style>

View File

@ -47,7 +47,7 @@ import {success} from '@/message'
import type { IconProp } from '@fortawesome/fontawesome-svg-core' import type { IconProp } from '@fortawesome/fontawesome-svg-core'
const props = defineProps({ const props = defineProps({
entity: String, entity: String as ISubscription['entity'],
entityId: Number, entityId: Number,
isButton: { isButton: {
type: Boolean, type: Boolean,
@ -73,12 +73,6 @@ const {t} = useI18n({useScope: 'global'})
const tooltipText = computed(() => { const tooltipText = computed(() => {
if (disabled.value) { if (disabled.value) {
if (props.entity === 'project' && subscriptionEntity.value === 'namespace') {
return t('task.subscription.subscribedProjectThroughParentNamespace')
}
if (props.entity === 'task' && subscriptionEntity.value === 'namespace') {
return t('task.subscription.subscribedTaskThroughParentNamespace')
}
if (props.entity === 'task' && subscriptionEntity.value === 'project') { if (props.entity === 'task' && subscriptionEntity.value === 'project') {
return t('task.subscription.subscribedTaskThroughParentProject') return t('task.subscription.subscribedTaskThroughParentProject')
} }
@ -87,10 +81,6 @@ const tooltipText = computed(() => {
} }
switch (props.entity) { switch (props.entity) {
case 'namespace':
return props.modelValue !== null ?
t('task.subscription.subscribedNamespace') :
t('task.subscription.notSubscribedNamespace')
case 'project': case 'project':
return props.modelValue !== null ? return props.modelValue !== null ?
t('task.subscription.subscribedProject') : t('task.subscription.subscribedProject') :
@ -130,9 +120,6 @@ async function subscribe() {
let message = '' let message = ''
switch (props.entity) { switch (props.entity) {
case 'namespace':
message = t('task.subscription.subscribeSuccessNamespace')
break
case 'project': case 'project':
message = t('task.subscription.subscribeSuccessProject') message = t('task.subscription.subscribeSuccessProject')
break break
@ -153,9 +140,6 @@ async function unsubscribe() {
let message = '' let message = ''
switch (props.entity) { switch (props.entity) {
case 'namespace':
message = t('task.subscription.unsubscribeSuccessNamespace')
break
case 'project': case 'project':
message = t('task.subscription.unsubscribeSuccessProject') message = t('task.subscription.unsubscribeSuccessProject')
break break

View File

@ -1,103 +0,0 @@
<template>
<dropdown>
<template #trigger="triggerProps">
<slot name="trigger" v-bind="triggerProps">
<BaseButton class="dropdown-trigger" @click="triggerProps.toggleOpen">
<icon icon="ellipsis-h" class="icon"/>
</BaseButton>
</slot>
</template>
<template v-if="namespace.isArchived">
<dropdown-item
:to="{ name: 'namespace.settings.archive', params: { id: namespace.id } }"
icon="archive"
>
{{ $t('menu.unarchive') }}
</dropdown-item>
</template>
<template v-else>
<dropdown-item
:to="{ name: 'namespace.settings.edit', params: { id: namespace.id } }"
icon="pen"
>
{{ $t('menu.edit') }}
</dropdown-item>
<dropdown-item
:to="{ name: 'namespace.settings.share', params: { namespaceId: namespace.id } }"
icon="share-alt"
>
{{ $t('menu.share') }}
</dropdown-item>
<dropdown-item
:to="{ name: 'project.create', params: { namespaceId: namespace.id } }"
icon="plus"
>
{{ $t('menu.newProject') }}
</dropdown-item>
<dropdown-item
:to="{ name: 'namespace.settings.archive', params: { id: namespace.id } }"
icon="archive"
>
{{ $t('menu.archive') }}
</dropdown-item>
<Subscription
class="has-no-shadow"
:is-button="false"
entity="namespace"
:entity-id="namespace.id"
:model-value="subscription"
@update:model-value="setSubscriptionInStore"
type="dropdown"
/>
<dropdown-item
:to="{ name: 'namespace.settings.delete', params: { id: namespace.id } }"
icon="trash-alt"
class="has-text-danger"
>
{{ $t('menu.delete') }}
</dropdown-item>
</template>
</dropdown>
</template>
<script setup lang="ts">
import {ref, onMounted, type PropType} from 'vue'
import BaseButton from '@/components/base/BaseButton.vue'
import Dropdown from '@/components/misc/dropdown.vue'
import DropdownItem from '@/components/misc/dropdown-item.vue'
import Subscription from '@/components/misc/subscription.vue'
import type {INamespace} from '@/modelTypes/INamespace'
import type {ISubscription} from '@/modelTypes/ISubscription'
import {useNamespaceStore} from '@/stores/namespaces'
const props = defineProps({
namespace: {
type: Object as PropType<INamespace>,
required: true,
},
})
const namespaceStore = useNamespaceStore()
const subscription = ref<ISubscription | null>(null)
onMounted(() => {
subscription.value = props.namespace.subscription
})
function setSubscriptionInStore(sub: ISubscription) {
subscription.value = sub
namespaceStore.setNamespaceById({
...props.namespace,
subscription: sub,
})
}
</script>
<style scoped lang="scss">
.dropdown-trigger {
padding: 0.5rem;
display: flex;
}
</style>

View File

@ -1,9 +1,13 @@
<template> <template>
<div <div
:class="{ 'is-loading': projectService.loading, 'is-archived': currentProject.isArchived}" :class="{ 'is-loading': projectService.loading, 'is-archived': currentProject?.isArchived}"
class="loader-container" class="loader-container"
> >
<div class="switch-view-container"> <h1 class="project-title-print">
{{ getProjectTitle(currentProject) }}
</h1>
<div class="switch-view-container d-print-none">
<div class="switch-view"> <div class="switch-view">
<BaseButton <BaseButton
v-shortcut="'g l'" v-shortcut="'g l'"
@ -45,8 +49,8 @@
<slot name="header" /> <slot name="header" />
</div> </div>
<CustomTransition name="fade"> <CustomTransition name="fade">
<Message variant="warning" v-if="currentProject.isArchived" class="mb-4"> <Message variant="warning" v-if="currentProject?.isArchived" class="mb-4">
{{ $t('project.archived') }} {{ $t('project.archivedMessage') }}
</Message> </Message>
</CustomTransition> </CustomTransition>
@ -98,7 +102,7 @@ const currentProject = computed(() => {
maxRight: null, maxRight: null,
} : baseStore.currentProject } : baseStore.currentProject
}) })
useTitle(() => currentProject.value.id ? getProjectTitle(currentProject.value) : '') useTitle(() => currentProject.value?.id ? getProjectTitle(currentProject.value) : '')
// watchEffect would be called every time the prop would get a value assigned, even if that value was the same as before. // watchEffect would be called every time the prop would get a value assigned, even if that value was the same as before.
// This resulted in loading and setting the project multiple times, even when navigating away from it. // This resulted in loading and setting the project multiple times, even when navigating away from it.
@ -118,7 +122,7 @@ watch(
( (
projectIdToLoad === loadedProjectId.value || projectIdToLoad === loadedProjectId.value ||
typeof projectIdToLoad === 'undefined' || typeof projectIdToLoad === 'undefined' ||
projectIdToLoad === currentProject.value.id projectIdToLoad === currentProject.value?.id
) )
&& typeof currentProject.value !== 'undefined' && currentProject.value.maxRight !== null && typeof currentProject.value !== 'undefined' && currentProject.value.maxRight !== null
) { ) {
@ -130,8 +134,8 @@ watch(
// Set the current project to the one we're about to load so that the title is already shown at the top // Set the current project to the one we're about to load so that the title is already shown at the top
loadedProjectId.value = 0 loadedProjectId.value = 0
const projectFromStore = projectStore.getProjectById(projectData.id) const projectFromStore = projectStore.projects[projectData.id]
if (projectFromStore !== null) { if (projectFromStore) {
baseStore.setBackground(null) baseStore.setBackground(null)
baseStore.setBlurHash(null) baseStore.setBlurHash(null)
baseStore.handleSetCurrentProject({project: projectFromStore}) baseStore.handleSetCurrentProject({project: projectFromStore})
@ -197,4 +201,15 @@ watch(
.is-archived .notification.is-warning { .is-archived .notification.is-warning {
margin-bottom: 1rem; margin-bottom: 1rem;
} }
.project-title-print {
display: none;
font-size: 1.75rem;
text-align: center;
margin-bottom: .5rem;
@media print {
display: block;
}
}
</style> </style>

View File

@ -15,7 +15,7 @@
:class="{'is-visible': background}" :class="{'is-visible': background}"
:style="{'background-image': background !== null ? `url(${background})` : undefined}" :style="{'background-image': background !== null ? `url(${background})` : undefined}"
/> />
<span v-if="project.isArchived" class="is-archived" >{{ $t('namespace.archived') }}</span> <span v-if="project.isArchived" class="is-archived" >{{ $t('project.archived') }}</span>
<div class="project-title" aria-hidden="true">{{ project.title }}</div> <div class="project-title" aria-hidden="true">{{ project.title }}</div>
<BaseButton <BaseButton

View File

@ -147,6 +147,7 @@
<label class="label">{{ $t('task.attributes.labels') }}</label> <label class="label">{{ $t('task.attributes.labels') }}</label>
<div class="control labels-list"> <div class="control labels-list">
<edit-labels <edit-labels
:creatable="false"
v-model="entities.labels" v-model="entities.labels"
@update:model-value="changeLabelFilter" @update:model-value="changeLabelFilter"
/> />
@ -165,16 +166,6 @@
/> />
</div> </div>
</div> </div>
<div class="field">
<label class="label">{{ $t('namespace.namespaces') }}</label>
<div class="control">
<SelectNamespace
v-model="entities.namespace"
@select="changeMultiselectFilter('namespace', 'namespace')"
@remove="changeMultiselectFilter('namespace', 'namespace')"
/>
</div>
</div>
</template> </template>
</card> </card>
</template> </template>
@ -189,7 +180,6 @@ import {camelCase} from 'camel-case'
import type {ILabel} from '@/modelTypes/ILabel' import type {ILabel} from '@/modelTypes/ILabel'
import type {IUser} from '@/modelTypes/IUser' import type {IUser} from '@/modelTypes/IUser'
import type {INamespace} from '@/modelTypes/INamespace'
import type {IProject} from '@/modelTypes/IProject' import type {IProject} from '@/modelTypes/IProject'
import {useLabelStore} from '@/stores/labels' import {useLabelStore} from '@/stores/labels'
@ -201,7 +191,6 @@ import EditLabels from '@/components/tasks/partials/editLabels.vue'
import Fancycheckbox from '@/components/input/fancycheckbox.vue' import Fancycheckbox from '@/components/input/fancycheckbox.vue'
import SelectUser from '@/components/input/SelectUser.vue' import SelectUser from '@/components/input/SelectUser.vue'
import SelectProject from '@/components/input/SelectProject.vue' import SelectProject from '@/components/input/SelectProject.vue'
import SelectNamespace from '@/components/input/SelectNamespace.vue'
import {parseDateOrString} from '@/helpers/time/parseDateOrString' import {parseDateOrString} from '@/helpers/time/parseDateOrString'
import {dateIsValid, formatISO} from '@/helpers/time/formatDate' import {dateIsValid, formatISO} from '@/helpers/time/formatDate'
@ -209,7 +198,6 @@ import {objectToSnakeCase} from '@/helpers/case'
import UserService from '@/services/user' import UserService from '@/services/user'
import ProjectService from '@/services/project' import ProjectService from '@/services/project'
import NamespaceService from '@/services/namespace'
// FIXME: do not use this here for now. instead create new version from DEFAULT_PARAMS // FIXME: do not use this here for now. instead create new version from DEFAULT_PARAMS
import {getDefaultParams} from '@/composables/useTaskList' import {getDefaultParams} from '@/composables/useTaskList'
@ -240,7 +228,6 @@ const DEFAULT_FILTERS = {
assignees: '', assignees: '',
labels: '', labels: '',
project_id: '', project_id: '',
namespace: '',
} as const } as const
const props = defineProps({ const props = defineProps({
@ -265,23 +252,20 @@ const filters = ref({...DEFAULT_FILTERS})
const services = { const services = {
users: shallowReactive(new UserService()), users: shallowReactive(new UserService()),
projects: shallowReactive(new ProjectService()), projects: shallowReactive(new ProjectService()),
namespace: shallowReactive(new NamespaceService()),
} }
interface Entities { interface Entities {
users: IUser[] users: IUser[]
labels: ILabel[] labels: ILabel[]
projects: IProject[] projects: IProject[]
namespace: INamespace[]
} }
type EntityType = 'users' | 'labels' | 'projects' | 'namespace' type EntityType = 'users' | 'labels' | 'projects'
const entities: Entities = reactive({ const entities: Entities = reactive({
users: [], users: [],
labels: [], labels: [],
projects: [], projects: [],
namespace: [],
}) })
onMounted(() => { onMounted(() => {
@ -328,7 +312,6 @@ function prepareFilters() {
prepareDate('reminders') prepareDate('reminders')
prepareRelatedObjectFilter('users', 'assignees') prepareRelatedObjectFilter('users', 'assignees')
prepareRelatedObjectFilter('projects', 'project_id') prepareRelatedObjectFilter('projects', 'project_id')
prepareRelatedObjectFilter('namespace')
prepareSingleValue('labels') prepareSingleValue('labels')

View File

@ -72,6 +72,13 @@
@update:model-value="setSubscriptionInStore" @update:model-value="setSubscriptionInStore"
type="dropdown" type="dropdown"
/> />
<dropdown-item
v-if="level < 2"
:to="{ name: 'project.createFromParent', params: { parentProjectId: project.id } }"
icon="layer-group"
>
{{ $t('menu.createProject') }}
</dropdown-item>
<dropdown-item <dropdown-item
:to="{ name: 'project.settings.delete', params: { projectId: project.id } }" :to="{ name: 'project.settings.delete', params: { projectId: project.id } }"
icon="trash-alt" icon="trash-alt"
@ -96,17 +103,18 @@ import type {ISubscription} from '@/modelTypes/ISubscription'
import {isSavedFilter} from '@/services/savedFilter' import {isSavedFilter} from '@/services/savedFilter'
import {useConfigStore} from '@/stores/config' import {useConfigStore} from '@/stores/config'
import {useProjectStore} from '@/stores/projects' import {useProjectStore} from '@/stores/projects'
import {useNamespaceStore} from '@/stores/namespaces'
const props = defineProps({ const props = defineProps({
project: { project: {
type: Object as PropType<IProject>, type: Object as PropType<IProject>,
required: true, required: true,
}, },
level: {
type: Number,
},
}) })
const projectStore = useProjectStore() const projectStore = useProjectStore()
const namespaceStore = useNamespaceStore()
const subscription = ref<ISubscription | null>(null) const subscription = ref<ISubscription | null>(null)
watchEffect(() => { watchEffect(() => {
subscription.value = props.project.subscription ?? null subscription.value = props.project.subscription ?? null
@ -122,6 +130,5 @@ function setSubscriptionInStore(sub: ISubscription) {
subscription: sub, subscription: sub,
} }
projectStore.setProject(updatedProject) projectStore.setProject(updatedProject)
namespaceStore.setProjectInNamespaceById(updatedProject)
} }
</script> </script>

View File

@ -61,7 +61,6 @@ import {useRouter} from 'vue-router'
import TaskService from '@/services/task' import TaskService from '@/services/task'
import TeamService from '@/services/team' import TeamService from '@/services/team'
import NamespaceModel from '@/models/namespace'
import TeamModel from '@/models/team' import TeamModel from '@/models/team'
import ProjectModel from '@/models/project' import ProjectModel from '@/models/project'
@ -70,7 +69,6 @@ import QuickAddMagic from '@/components/tasks/partials/quick-add-magic.vue'
import {useBaseStore} from '@/stores/base' import {useBaseStore} from '@/stores/base'
import {useProjectStore} from '@/stores/projects' import {useProjectStore} from '@/stores/projects'
import {useNamespaceStore} from '@/stores/namespaces'
import {useLabelStore} from '@/stores/labels' import {useLabelStore} from '@/stores/labels'
import {useTaskStore} from '@/stores/tasks' import {useTaskStore} from '@/stores/tasks'
@ -81,7 +79,6 @@ import {success} from '@/message'
import type {ITeam} from '@/modelTypes/ITeam' import type {ITeam} from '@/modelTypes/ITeam'
import type {ITask} from '@/modelTypes/ITask' import type {ITask} from '@/modelTypes/ITask'
import type {INamespace} from '@/modelTypes/INamespace'
import type {IProject} from '@/modelTypes/IProject' import type {IProject} from '@/modelTypes/IProject'
const {t} = useI18n({useScope: 'global'}) const {t} = useI18n({useScope: 'global'})
@ -89,7 +86,6 @@ const router = useRouter()
const baseStore = useBaseStore() const baseStore = useBaseStore()
const projectStore = useProjectStore() const projectStore = useProjectStore()
const namespaceStore = useNamespaceStore()
const labelStore = useLabelStore() const labelStore = useLabelStore()
const taskStore = useTaskStore() const taskStore = useTaskStore()
@ -105,7 +101,6 @@ enum ACTION_TYPE {
enum COMMAND_TYPE { enum COMMAND_TYPE {
NEW_TASK = 'newTask', NEW_TASK = 'newTask',
NEW_PROJECT = 'newProject', NEW_PROJECT = 'newProject',
NEW_NAMESPACE = 'newNamespace',
NEW_TEAM = 'newTeam', NEW_TEAM = 'newTeam',
} }
@ -147,24 +142,15 @@ const foundProjects = computed(() => {
return [] return []
} }
const ncache: { [id: ProjectModel['id']]: INamespace } = {}
const history = getHistory() const history = getHistory()
const allProjects = [ const allProjects = [
...new Set([ ...new Set([
...history.map((l) => projectStore.getProjectById(l.id)), ...history.map((l) => projectStore.projects[l.id]),
...projectStore.searchProject(project), ...projectStore.searchProject(project),
]), ]),
] ]
return allProjects.filter((l) => { return allProjects.filter(l => Boolean(l))
if (typeof l === 'undefined' || l === null) {
return false
}
if (typeof ncache[l.namespaceId] === 'undefined') {
ncache[l.namespaceId] = namespaceStore.getNamespaceById(l.namespaceId)
}
return !ncache[l.namespaceId].isArchived
})
}) })
// FIXME: use fuzzysearch // FIXME: use fuzzysearch
@ -205,7 +191,6 @@ const results = computed<Result[]>(() => {
const loading = computed(() => const loading = computed(() =>
taskService.loading || taskService.loading ||
namespaceStore.isLoading ||
projectStore.isLoading || projectStore.isLoading ||
teamService.loading, teamService.loading,
) )
@ -230,12 +215,6 @@ const commands = computed<{ [key in COMMAND_TYPE]: Command }>(() => ({
placeholder: t('quickActions.newProject'), placeholder: t('quickActions.newProject'),
action: newProject, action: newProject,
}, },
newNamespace: {
type: COMMAND_TYPE.NEW_NAMESPACE,
title: t('quickActions.cmds.newNamespace'),
placeholder: t('quickActions.newNamespace'),
action: newNamespace,
},
newTeam: { newTeam: {
type: COMMAND_TYPE.NEW_TEAM, type: COMMAND_TYPE.NEW_TEAM,
title: t('quickActions.cmds.newTeam'), title: t('quickActions.cmds.newTeam'),
@ -252,7 +231,6 @@ const currentProject = computed(() => Object.keys(baseStore.currentProject).leng
) )
const hintText = computed(() => { const hintText = computed(() => {
let namespace
if (selectedCmd.value !== null && currentProject.value !== null) { if (selectedCmd.value !== null && currentProject.value !== null) {
switch (selectedCmd.value.type) { switch (selectedCmd.value.type) {
case COMMAND_TYPE.NEW_TASK: case COMMAND_TYPE.NEW_TASK:
@ -260,12 +238,7 @@ const hintText = computed(() => {
title: currentProject.value.title, title: currentProject.value.title,
}) })
case COMMAND_TYPE.NEW_PROJECT: case COMMAND_TYPE.NEW_PROJECT:
namespace = namespaceStore.getNamespaceById( return t('quickActions.createProject')
currentProject.value.namespaceId,
)
return t('quickActions.createProject', {
title: namespace?.title,
})
} }
} }
const prefixes = const prefixes =
@ -278,7 +251,7 @@ const availableCmds = computed(() => {
if (currentProject.value !== null) { if (currentProject.value !== null) {
cmds.push(commands.value.newTask, commands.value.newProject) cmds.push(commands.value.newTask, commands.value.newProject)
} }
cmds.push(commands.value.newNamespace, commands.value.newTeam) cmds.push(commands.value.newTeam)
return cmds return cmds
}) })
@ -396,7 +369,7 @@ function searchTasks() {
const r = await taskService.getAll({}, params) as DoAction<ITask>[] const r = await taskService.getAll({}, params) as DoAction<ITask>[]
foundTasks.value = r.map((t) => { foundTasks.value = r.map((t) => {
t.type = ACTION_TYPE.TASK t.type = ACTION_TYPE.TASK
const project = projectStore.getProjectById(t.projectId) const project = projectStore.projects[t.projectId]
if (project !== null) { if (project !== null) {
t.title = `${t.title} (${project.title})` t.title = `${t.title} (${project.title})`
} }
@ -504,21 +477,10 @@ async function newProject() {
if (currentProject.value === null) { if (currentProject.value === null) {
return return
} }
const newProject = await projectStore.createProject(new ProjectModel({ await projectStore.createProject(new ProjectModel({
title: query.value, title: query.value,
namespaceId: currentProject.value.namespaceId,
})) }))
success({ message: t('project.create.createdSuccess')}) success({ message: t('project.create.createdSuccess')})
await router.push({
name: 'project.index',
params: { projectId: newProject.id },
})
}
async function newNamespace() {
const newNamespace = new NamespaceModel({ title: query.value })
await namespaceStore.createNamespace(newNamespace)
success({ message: t('namespace.create.success') })
} }
async function newTeam() { async function newTeam() {

View File

@ -139,10 +139,6 @@ import {ref, reactive, computed, shallowReactive, type Ref} from 'vue'
import type {PropType} from 'vue' import type {PropType} from 'vue'
import {useI18n} from 'vue-i18n' import {useI18n} from 'vue-i18n'
import UserNamespaceService from '@/services/userNamespace'
import UserNamespaceModel from '@/models/userNamespace'
import type {IUserNamespace} from '@/modelTypes/IUserNamespace'
import UserProjectService from '@/services/userProject' import UserProjectService from '@/services/userProject'
import UserProjectModel from '@/models/userProject' import UserProjectModel from '@/models/userProject'
import type {IUserProject} from '@/modelTypes/IUserProject' import type {IUserProject} from '@/modelTypes/IUserProject'
@ -151,10 +147,6 @@ import UserService from '@/services/user'
import UserModel, { getDisplayName } from '@/models/user' import UserModel, { getDisplayName } from '@/models/user'
import type {IUser} from '@/modelTypes/IUser' import type {IUser} from '@/modelTypes/IUser'
import TeamNamespaceService from '@/services/teamNamespace'
import TeamNamespaceModel from '@/models/teamNamespace'
import type { ITeamNamespace } from '@/modelTypes/ITeamNamespace'
import TeamProjectService from '@/services/teamProject' import TeamProjectService from '@/services/teamProject'
import TeamProjectModel from '@/models/teamProject' import TeamProjectModel from '@/models/teamProject'
import type { ITeamProject } from '@/modelTypes/ITeamProject' import type { ITeamProject } from '@/modelTypes/ITeamProject'
@ -170,13 +162,15 @@ import Nothing from '@/components/misc/nothing.vue'
import {success} from '@/message' import {success} from '@/message'
import {useAuthStore} from '@/stores/auth' import {useAuthStore} from '@/stores/auth'
// FIXME: I think this whole thing can now only manage user/team sharing for projects? Maybe remove a little generalization?
const props = defineProps({ const props = defineProps({
type: { type: {
type: String as PropType<'project' | 'namespace'>, type: String as PropType<'project'>,
default: '', default: '',
}, },
shareType: { shareType: {
type: String as PropType<'user' | 'team' | 'namespace'>, type: String as PropType<'user' | 'team'>,
default: '', default: '',
}, },
id: { id: {
@ -191,9 +185,9 @@ const props = defineProps({
const {t} = useI18n({useScope: 'global'}) const {t} = useI18n({useScope: 'global'})
// This user service is either a userNamespaceService or a userProjectService, depending on the type we are using // This user service is a userProjectService, depending on the type we are using
let stuffService: UserNamespaceService | UserProjectService | TeamProjectService | TeamNamespaceService let stuffService: UserProjectService | TeamProjectService
let stuffModel: IUserNamespace | IUserProject | ITeamProject | ITeamNamespace let stuffModel: IUserProject | ITeamProject
let searchService: UserService | TeamService let searchService: UserService | TeamService
let sharable: Ref<IUser | ITeam> let sharable: Ref<IUser | ITeam>
@ -231,10 +225,6 @@ const sharableName = computed(() => {
return t('project.list.title') return t('project.list.title')
} }
if (props.shareType === 'namespace') {
return t('namespace.namespace')
}
return '' return ''
}) })
@ -247,11 +237,6 @@ if (props.shareType === 'user') {
if (props.type === 'project') { if (props.type === 'project') {
stuffService = shallowReactive(new UserProjectService()) stuffService = shallowReactive(new UserProjectService())
stuffModel = reactive(new UserProjectModel({projectId: props.id})) stuffModel = reactive(new UserProjectModel({projectId: props.id}))
} else if (props.type === 'namespace') {
stuffService = shallowReactive(new UserNamespaceService())
stuffModel = reactive(new UserNamespaceModel({
namespaceId: props.id,
}))
} else { } else {
throw new Error('Unknown type: ' + props.type) throw new Error('Unknown type: ' + props.type)
} }
@ -264,11 +249,6 @@ if (props.shareType === 'user') {
if (props.type === 'project') { if (props.type === 'project') {
stuffService = shallowReactive(new TeamProjectService()) stuffService = shallowReactive(new TeamProjectService())
stuffModel = reactive(new TeamProjectModel({projectId: props.id})) stuffModel = reactive(new TeamProjectModel({projectId: props.id}))
} else if (props.type === 'namespace') {
stuffService = shallowReactive(new TeamNamespaceService())
stuffModel = reactive(new TeamNamespaceModel({
namespaceId: props.id,
}))
} else { } else {
throw new Error('Unknown type: ' + props.type) throw new Error('Unknown type: ' + props.type)
} }

View File

@ -7,7 +7,7 @@
:search-results="foundLabels" :search-results="foundLabels"
@select="addLabel" @select="addLabel"
label="title" label="title"
:creatable="true" :creatable="creatable"
@create="createAndAddLabel" @create="createAndAddLabel"
:create-placeholder="$t('task.label.createPlaceholder')" :create-placeholder="$t('task.label.createPlaceholder')"
v-model="labels" v-model="labels"
@ -65,6 +65,10 @@ const props = defineProps({
disabled: { disabled: {
default: false, default: false,
}, },
creatable: {
type: Boolean,
default: true,
},
}) })
const emit = defineEmits(['update:modelValue']) const emit = defineEmits(['update:modelValue'])

View File

@ -11,8 +11,10 @@
@search="findProjects" @search="findProjects"
> >
<template #searchResult="{option}"> <template #searchResult="{option}">
<span class="project-namespace-title search-result">{{ namespace((option as IProject).namespaceId) }} ></span> <span class="has-text-grey" v-if="projectStore.getAncestors(option).length > 1">
{{ (option as IProject).title }} {{ projectStore.getAncestors(option).filter(p => p.id !== option.id).map(p => getProjectTitle(p)).join(' &gt; ') }} &gt;
</span>
{{ getProjectTitle(option) }}
</template> </template>
</Multiselect> </Multiselect>
</template> </template>
@ -20,13 +22,11 @@
<script lang="ts" setup> <script lang="ts" setup>
import {reactive, ref, watch} from 'vue' import {reactive, ref, watch} from 'vue'
import type {PropType} from 'vue' import type {PropType} from 'vue'
import {useI18n} from 'vue-i18n'
import type {IProject} from '@/modelTypes/IProject' import type {IProject} from '@/modelTypes/IProject'
import type {INamespace} from '@/modelTypes/INamespace'
import {useProjectStore} from '@/stores/projects' import {useProjectStore} from '@/stores/projects'
import {useNamespaceStore} from '@/stores/namespaces' import {getProjectTitle} from '@/helpers/getProjectTitle'
import ProjectModel from '@/models/project' import ProjectModel from '@/models/project'
@ -40,8 +40,6 @@ const props = defineProps({
}) })
const emit = defineEmits(['update:modelValue']) const emit = defineEmits(['update:modelValue'])
const {t} = useI18n({useScope: 'global'})
const project: IProject = reactive(new ProjectModel()) const project: IProject = reactive(new ProjectModel())
watch( watch(
@ -54,7 +52,6 @@ watch(
) )
const projectStore = useProjectStore() const projectStore = useProjectStore()
const namespaceStore = useNamespaceStore()
const foundProjects = ref<IProject[]>([]) const foundProjects = ref<IProject[]>([])
function findProjects(query: string) { function findProjects(query: string) {
if (query === '') { if (query === '') {
@ -70,17 +67,4 @@ function select(l: IProject | null) {
Object.assign(project, l) Object.assign(project, l)
emit('update:modelValue', project) emit('update:modelValue', project)
} }
function namespace(namespaceId: INamespace['id']) {
const namespace = namespaceStore.getNamespaceById(namespaceId)
return namespace !== null
? namespace.title
: t('project.shared')
}
</script> </script>
<style lang="scss" scoped>
.project-namespace-title {
color: var(--grey-500);
}
</style>

View File

@ -46,11 +46,6 @@
class="different-project" class="different-project"
v-if="task.projectId !== projectId" v-if="task.projectId !== projectId"
> >
<span
v-if="task.differentNamespace !== null"
v-tooltip="$t('task.relation.differentNamespace')">
{{ task.differentNamespace }} >
</span>
<span <span
v-if="task.differentProject !== null" v-if="task.differentProject !== null"
v-tooltip="$t('task.relation.differentProject')"> v-tooltip="$t('task.relation.differentProject')">
@ -101,11 +96,6 @@
class="different-project" class="different-project"
v-if="t.projectId !== projectId" v-if="t.projectId !== projectId"
> >
<span
v-if="t.differentNamespace !== null"
v-tooltip="$t('task.relation.differentNamespace')">
{{ t.differentNamespace }} >
</span>
<span <span
v-if="t.differentProject !== null" v-if="t.differentProject !== null"
v-tooltip="$t('task.relation.differentProject')"> v-tooltip="$t('task.relation.differentProject')">
@ -168,10 +158,9 @@ import BaseButton from '@/components/base/BaseButton.vue'
import Multiselect from '@/components/input/multiselect.vue' import Multiselect from '@/components/input/multiselect.vue'
import Fancycheckbox from '@/components/input/fancycheckbox.vue' import Fancycheckbox from '@/components/input/fancycheckbox.vue'
import {useNamespaceStore} from '@/stores/namespaces'
import {error, success} from '@/message' import {error, success} from '@/message'
import {useTaskStore} from '@/stores/tasks' import {useTaskStore} from '@/stores/tasks'
import {useProjectStore} from '@/stores/projects'
const props = defineProps({ const props = defineProps({
taskId: { taskId: {
@ -196,7 +185,7 @@ const props = defineProps({
}) })
const taskStore = useTaskStore() const taskStore = useTaskStore()
const namespaceStore = useNamespaceStore() const projectStore = useProjectStore()
const route = useRoute() const route = useRoute()
const {t} = useI18n({useScope: 'global'}) const {t} = useI18n({useScope: 'global'})
@ -230,26 +219,15 @@ async function findTasks(newQuery: string) {
foundTasks.value = await taskService.getAll({}, {s: newQuery}) foundTasks.value = await taskService.getAll({}, {s: newQuery})
} }
const getProjectAndNamespaceById = (projectId: number) => namespaceStore.getProjectAndNamespaceById(projectId, true)
const namespace = computed(() => getProjectAndNamespaceById(props.projectId)?.namespace)
function mapRelatedTasks(tasks: ITask[]) { function mapRelatedTasks(tasks: ITask[]) {
return tasks.map(task => { return tasks.map(task => {
// by doing this here once we can save a lot of duplicate calls in the template // by doing this here once we can save a lot of duplicate calls in the template
const { const project = projectStore.projects[task.ProjectId]
project,
namespace: taskNamespace,
} = getProjectAndNamespaceById(task.projectId) || {project: null, namespace: null}
return { return {
...task, ...task,
differentNamespace:
(taskNamespace !== null &&
taskNamespace.id !== namespace.value.id &&
taskNamespace?.title) || null,
differentProject: differentProject:
(project !== null && (project &&
task.projectId !== props.projectId && task.projectId !== props.projectId &&
project?.title) || null, project?.title) || null,
} }

View File

@ -7,19 +7,19 @@
/> />
<ColorBubble <ColorBubble
v-if="showProjectColor && projectColor !== '' && currentProject.id !== task.projectId" v-if="showProjectColor && projectColor !== '' && currentProject?.id !== task.projectId"
:color="projectColor" :color="projectColor"
class="mr-1" class="mr-1"
/> />
<router-link <router-link
:to="taskDetailRoute" :to="taskDetailRoute"
:class="{ 'done': task.done, 'show-project': showProject && project !== null}" :class="{ 'done': task.done, 'show-project': showProject && project}"
class="tasktext" class="tasktext"
> >
<span> <span>
<router-link <router-link
v-if="showProject && project !== null" v-if="showProject && typeof project !== 'undefined'"
:to="{ name: 'project.list', params: { projectId: task.projectId } }" :to="{ name: 'project.list', params: { projectId: task.projectId } }"
class="task-project" class="task-project"
:class="{'mr-2': task.hexColor !== ''}" :class="{'mr-2': task.hexColor !== ''}"
@ -34,7 +34,7 @@
/> />
<!-- Show any parent tasks to make it clear this task is a sub task of something --> <!-- Show any parent tasks to make it clear this task is a sub task of something -->
<span class="parent-tasks" v-if="typeof task.relatedTasks.parenttask !== 'undefined'"> <span class="parent-tasks" v-if="typeof task.relatedTasks?.parenttask !== 'undefined'">
<template v-for="(pt, i) in task.relatedTasks.parenttask"> <template v-for="(pt, i) in task.relatedTasks.parenttask">
{{ pt.title }}<template v-if="(i + 1) < task.relatedTasks.parenttask.length">,&nbsp;</template> {{ pt.title }}<template v-if="(i + 1) < task.relatedTasks.parenttask.length">,&nbsp;</template>
</template> </template>
@ -105,7 +105,7 @@
</progress> </progress>
<router-link <router-link
v-if="!showProject && currentProject.id !== task.projectId && project !== null" v-if="!showProject && currentProject?.id !== task.projectId && project"
:to="{ name: 'project.list', params: { projectId: task.projectId } }" :to="{ name: 'project.list', params: { projectId: task.projectId } }"
class="task-project" class="task-project"
v-tooltip="$t('task.detail.belongsToProject', {project: project.title})" v-tooltip="$t('task.detail.belongsToProject', {project: project.title})"
@ -150,7 +150,6 @@ import {formatDateSince, formatISO, formatDateLong} from '@/helpers/time/formatD
import {success} from '@/message' import {success} from '@/message'
import {useProjectStore} from '@/stores/projects' import {useProjectStore} from '@/stores/projects'
import {useNamespaceStore} from '@/stores/namespaces'
import {useBaseStore} from '@/stores/base' import {useBaseStore} from '@/stores/base'
import {useTaskStore} from '@/stores/tasks' import {useTaskStore} from '@/stores/tasks'
@ -210,10 +209,9 @@ onBeforeUnmount(() => {
const baseStore = useBaseStore() const baseStore = useBaseStore()
const projectStore = useProjectStore() const projectStore = useProjectStore()
const taskStore = useTaskStore() const taskStore = useTaskStore()
const namespaceStore = useNamespaceStore()
const project = computed(() => projectStore.getProjectById(task.value.projectId)) const project = computed(() => projectStore.projects[task.value.projectId])
const projectColor = computed(() => project.value !== null ? project.value.hexColor : '') const projectColor = computed(() => project.value ? project.value?.hexColor : '')
const currentProject = computed(() => { const currentProject = computed(() => {
return typeof baseStore.currentProject === 'undefined' ? { return typeof baseStore.currentProject === 'undefined' ? {
@ -258,10 +256,8 @@ function undoDone(checked: boolean) {
} }
async function toggleFavorite() { async function toggleFavorite() {
task.value.isFavorite = !task.value.isFavorite task.value = await taskStore.toggleFavorite(task.value)
task.value = await taskService.update(task.value)
emit('task-updated', task.value) emit('task-updated', task.value)
namespaceStore.loadNamespacesIfFavoritesDontExist()
} }
const deferDueDate = ref<typeof DeferTask | null>(null) const deferDueDate = ref<typeof DeferTask | null>(null)

View File

@ -1,19 +0,0 @@
import {ref, computed} from 'vue'
import {useNamespaceStore} from '@/stores/namespaces'
export function useNamespaceSearch() {
const query = ref('')
const namespaceStore = useNamespaceStore()
const namespaces = computed(() => namespaceStore.searchNamespace(query.value))
function findNamespaces(newQuery: string) {
query.value = newQuery
}
return {
namespaces,
findNamespaces,
}
}

View File

@ -0,0 +1,7 @@
export function canNestProjectDeeper(level: number) {
if (level < 2) {
return true
}
return level >= 2 && window.PROJECT_INFINITE_NESTING_ENABLED
}

View File

@ -1,15 +0,0 @@
import {i18n} from '@/i18n'
import type {INamespace} from '@/modelTypes/INamespace'
export const getNamespaceTitle = (n: INamespace) => {
if (n.id === -1) {
return i18n.global.t('namespace.pseudo.sharedProjects.title')
}
if (n.id === -2) {
return i18n.global.t('namespace.pseudo.favorites.title')
}
if (n.id === -3) {
return i18n.global.t('namespace.pseudo.savedFilters.title')
}
return n.title
}

View File

@ -1,9 +1,14 @@
import {i18n} from '@/i18n' import {i18n} from '@/i18n'
import type {IProject} from '@/modelTypes/IProject' import type {IProject} from '@/modelTypes/IProject'
export function getProjectTitle(l: IProject) { export function getProjectTitle(project: IProject) {
if (l.id === -1) { if (project.id === -1) {
return i18n.global.t('project.pseudo.favorites.title') return i18n.global.t('project.pseudo.favorites.title')
} }
return l.title
if (project.title === 'Inbox') {
return i18n.global.t('project.inboxTitle')
}
return project.title
} }

View File

@ -894,7 +894,10 @@
"color": "Change the color of this task", "color": "Change the color of this task",
"move": "Move this task to another project", "move": "Move this task to another project",
"reminder": "Manage reminders of this task", "reminder": "Manage reminders of this task",
"description": "Toggle editing of the task description" "description": "Toggle editing of the task description",
"delete": "Delete this task",
"priority": "Change the priority of this task",
"favorite": "Mark this task as favorite / unfavorite"
}, },
"project": { "project": {
"title": "Project Views", "title": "Project Views",
@ -1053,4 +1056,4 @@
"frontendVersion": "Frontend Version: {version}", "frontendVersion": "Frontend Version: {version}",
"apiVersion": "API Version: {version}" "apiVersion": "API Version: {version}"
} }
} }

View File

@ -894,7 +894,10 @@
"color": "Změnit barvu tohoto úkolu", "color": "Změnit barvu tohoto úkolu",
"move": "Move this task to another project", "move": "Move this task to another project",
"reminder": "Spravovat připomenutí této úlohy", "reminder": "Spravovat připomenutí této úlohy",
"description": "Přepnout úpravy popisu úkolu" "description": "Přepnout úpravy popisu úkolu",
"delete": "Delete this task",
"priority": "Change the priority of this task",
"favorite": "Mark this task as favorite / unfavorite"
}, },
"project": { "project": {
"title": "Project Views", "title": "Project Views",
@ -1053,4 +1056,4 @@
"frontendVersion": "Verze frontendu: {version}", "frontendVersion": "Verze frontendu: {version}",
"apiVersion": "Verze API: {version}" "apiVersion": "Verze API: {version}"
} }
} }

View File

@ -6,9 +6,7 @@
"welcomeEvening": "Godaften {username}!", "welcomeEvening": "Godaften {username}!",
"lastViewed": "Sidst vist", "lastViewed": "Sidst vist",
"project": { "project": {
"newText": "You can create a new project for your new tasks:", "importText": "Import your projects and tasks from other services into Vikunja:",
"new": "New project",
"importText": "Or import your projects and tasks from other services into Vikunja:",
"import": "Import your data into Vikunja" "import": "Import your data into Vikunja"
} }
}, },
@ -143,7 +141,7 @@
}, },
"deletion": { "deletion": {
"title": "Slet din Vikunja konto", "title": "Slet din Vikunja konto",
"text1": "The deletion of your account is permanent and cannot be undone. We will delete all your namespaces, projects, tasks and everything associated with it.", "text1": "The deletion of your account is permanent and cannot be undone. We will delete all your projects, tasks and everything associated with it.",
"text2": "For at fortsætte, skal du indtaste din adgangskode. Du vil modtage en e-mail med yderligere instruktioner.", "text2": "For at fortsætte, skal du indtaste din adgangskode. Du vil modtage en e-mail med yderligere instruktioner.",
"confirm": "Slet min konto", "confirm": "Slet min konto",
"requestSuccess": "Anmodningen blev gennemført. Du vil modtage en e-mail med yderligere instruktioner.", "requestSuccess": "Anmodningen blev gennemført. Du vil modtage en e-mail med yderligere instruktioner.",
@ -157,7 +155,7 @@
}, },
"export": { "export": {
"title": "Eksporter dine Vikunja-data", "title": "Eksporter dine Vikunja-data",
"description": "You can request a copy of all your Vikunja data. This include Namespaces, Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.", "description": "You can request a copy of all your Vikunja data. This includes Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
"descriptionPasswordRequired": "Indtast venligst din adgangskode for at fortsætte:", "descriptionPasswordRequired": "Indtast venligst din adgangskode for at fortsætte:",
"request": "Anmod om en kopi af mine Vikunja-data", "request": "Anmod om en kopi af mine Vikunja-data",
"success": "Du har anmodet om dine Vikunja-data! Vi sender dig en e-mail, når den er klar til hentning.", "success": "Du har anmodet om dine Vikunja-data! Vi sender dig en e-mail, når den er klar til hentning.",
@ -165,14 +163,18 @@
} }
}, },
"project": { "project": {
"archived": "This project is archived. It is not possible to create new or edit tasks for it.", "archivedMessage": "This project is archived. It is not possible to create new or edit tasks for it.",
"archived": "Archived",
"showArchived": "Show Archived",
"title": "Project Title", "title": "Project Title",
"color": "Color", "color": "Color",
"projects": "Projects", "projects": "Projects",
"parent": "Parent Project",
"search": "Type to search for a project…", "search": "Type to search for a project…",
"searchSelect": "Click or press enter to select this project", "searchSelect": "Click or press enter to select this project",
"shared": "Shared Projects", "shared": "Shared Projects",
"noDescriptionAvailable": "No project description is available.", "noDescriptionAvailable": "No project description is available.",
"inboxTitle": "Inbox",
"create": { "create": {
"header": "New project", "header": "New project",
"titlePlaceholder": "The project's title goes here…", "titlePlaceholder": "The project's title goes here…",
@ -210,7 +212,7 @@
"duplicate": { "duplicate": {
"title": "Duplicate this project", "title": "Duplicate this project",
"label": "Duplicate", "label": "Duplicate",
"text": "Select a namespace which should hold the duplicated project:", "text": "Select a parent project which should hold the duplicated project:",
"success": "The project was successfully duplicated." "success": "The project was successfully duplicated."
}, },
"edit": { "edit": {
@ -321,67 +323,6 @@
} }
} }
}, },
"namespace": {
"title": "Namespaces & Projects",
"namespace": "Navneområde",
"showArchived": "Vis arkiverede",
"noneAvailable": "Du har ingen navneområder lige nu.",
"unarchive": "Tilbagekald",
"archived": "Arkiveret",
"noProjects": "This namespace does not contain any projects.",
"createProject": "Create a new project in this namespace.",
"namespaces": "Navneområder",
"search": "Skriv for at søge efter et navneområde…",
"create": {
"title": "Nyt navneområde",
"titleRequired": "Angiv venligst en titel.",
"explanation": "A namespace is a collection of projects you can share and use to organize your projects with. In fact, every project belongs to a namespace.",
"tooltip": "Hvad er et navneområde?",
"success": "Navneområdet blev oprettet."
},
"archive": {
"titleArchive": "Arkiver \"{namespace}\"",
"titleUnarchive": "Fjern arkivering \"{namespace}\"",
"archiveText": "You won't be able to edit this namespace or create new projects until you un-archive it. This will also archive all projects in this namespace.",
"unarchiveText": "You will be able to create new projects or edit it.",
"success": "Navneområdet blev arkiveret.",
"unarchiveSuccess": "Navneområdet blev tilbagekaldt.",
"description": "If a namespace is archived, you cannot create new projects or edit it."
},
"delete": {
"title": "Slet \"{namespace}\"",
"text1": "Er du sikker på, at du vil slette dette navneområde og alt dets indhold?",
"text2": "This includes all projects and tasks and CANNOT BE UNDONE!",
"success": "Navneområdet blev slettet."
},
"edit": {
"title": "Rediger \"{namespace}\"",
"success": "Navneområdet blev opdateret."
},
"share": {
"title": "Del \"{namespace}\""
},
"attributes": {
"title": "Navneområde Titel",
"titlePlaceholder": "Navneområdets titel skrives her…",
"description": "Beskrivelse",
"descriptionPlaceholder": "Navneområdets beskrivelse skrives her…",
"color": "Farve",
"archived": "Er Arkiveret",
"isArchived": "Dette navneområde er arkiveret"
},
"pseudo": {
"sharedProjects": {
"title": "Shared Projects"
},
"favorites": {
"title": "Favoritter"
},
"savedFilters": {
"title": "Filtre"
}
}
},
"filters": { "filters": {
"title": "Filtre", "title": "Filtre",
"clear": "Ryd Filtre", "clear": "Ryd Filtre",
@ -403,7 +344,7 @@
}, },
"create": { "create": {
"title": "Nyt Gemt Filter", "title": "Nyt Gemt Filter",
"description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed. Once created, it will appear in a special namespace.", "description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed.",
"action": "Opret nyt gemt filter", "action": "Opret nyt gemt filter",
"titleRequired": "Please provide a title for the filter." "titleRequired": "Please provide a title for the filter."
}, },
@ -674,19 +615,13 @@
"updated": "Opdateret" "updated": "Opdateret"
}, },
"subscription": { "subscription": {
"subscribedProjectThroughParentNamespace": "You can't unsubscribe here because you are subscribed to this project through its namespace.",
"subscribedTaskThroughParentNamespace": "Du kan ikke afmelde dig her, fordi du abonnerer på denne opgave gennem dens navneområde.",
"subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.", "subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.",
"subscribedNamespace": "Du abonnerer i øjeblikket på dette navneområde og vil modtage notifikationer om ændringer.",
"notSubscribedNamespace": "Du abonnerer ikke på dette navneområde og modtager ikke notifikationer om ændringer.",
"subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.", "subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.",
"notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.", "notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.",
"subscribedTask": "Du abonnerer på denne opgave og vil modtage notifikationer om ændringer.", "subscribedTask": "Du abonnerer på denne opgave og vil modtage notifikationer om ændringer.",
"notSubscribedTask": "Du abonnerer ikke på denne opgave og modtager ikke notifikationer om ændringer.", "notSubscribedTask": "Du abonnerer ikke på denne opgave og modtager ikke notifikationer om ændringer.",
"subscribe": "Abonner", "subscribe": "Abonner",
"unsubscribe": "Afmeld", "unsubscribe": "Afmeld",
"subscribeSuccessNamespace": "Du abonnerer nu på dette navneområde",
"unsubscribeSuccessNamespace": "Du er nu afmeldt dette navneområde",
"subscribeSuccessProject": "You are now subscribed to this project", "subscribeSuccessProject": "You are now subscribed to this project",
"unsubscribeSuccessProject": "You are now unsubscribed to this project", "unsubscribeSuccessProject": "You are now unsubscribed to this project",
"subscribeSuccessTask": "Du abonnerer nu på denne opgave", "subscribeSuccessTask": "Du abonnerer nu på denne opgave",
@ -763,7 +698,6 @@
"searchPlaceholder": "Indtast søgning efter en ny opgave der tilføjes som relateret…", "searchPlaceholder": "Indtast søgning efter en ny opgave der tilføjes som relateret…",
"createPlaceholder": "Tilføj dette som en ny relateret opgave", "createPlaceholder": "Tilføj dette som en ny relateret opgave",
"differentProject": "This task belongs to a different project.", "differentProject": "This task belongs to a different project.",
"differentNamespace": "Denne opgave hører til et andet navneområde.",
"noneYet": "Ingen opgaverelationer endnu.", "noneYet": "Ingen opgaverelationer endnu.",
"delete": "Slet Opgaverelation", "delete": "Slet Opgaverelation",
"deleteText1": "Er du sikker på, at du vil slette denne opgaverelation?", "deleteText1": "Er du sikker på, at du vil slette denne opgaverelation?",
@ -848,19 +782,19 @@
"delete": { "delete": {
"header": "Slet holdet", "header": "Slet holdet",
"text1": "Er du sikker på du vil slette dette hold og alle dets medlemmer?", "text1": "Er du sikker på du vil slette dette hold og alle dets medlemmer?",
"text2": "All team members will lose access to projects and namespaces shared with this team. This CANNOT BE UNDONE!", "text2": "All team members will lose access to projects shared with this team. This CANNOT BE UNDONE!",
"success": "Holdet blev slettet." "success": "Holdet blev slettet."
}, },
"deleteUser": { "deleteUser": {
"header": "Fjern en bruger fra holdet", "header": "Fjern en bruger fra holdet",
"text1": "Er du sikker på du vil fjerne denne bruger fra holdet?", "text1": "Er du sikker på du vil fjerne denne bruger fra holdet?",
"text2": "They will lose access to all projects and namespaces this team has access to. This CANNOT BE UNDONE!", "text2": "They will lose access to all projects this team has access to. This CANNOT BE UNDONE!",
"success": "Brugeren blev fjernet fra holdet." "success": "Brugeren blev fjernet fra holdet."
}, },
"leave": { "leave": {
"title": "Forlad hold", "title": "Forlad hold",
"text1": "Er du sikker på du vil forlade dette hold?", "text1": "Er du sikker på du vil forlade dette hold?",
"text2": "You will lose access to all projects and namespaces this team has access to. If you change your mind you'll need a team admin to add you again.", "text2": "You will lose access to all projects this team has access to. If you change your mind you'll need a team admin to add you again.",
"success": "Du har forladt holdet." "success": "Du har forladt holdet."
} }
}, },
@ -894,7 +828,10 @@
"color": "Skift farven på denne opgave", "color": "Skift farven på denne opgave",
"move": "Move this task to another project", "move": "Move this task to another project",
"reminder": "Administrer påmindelser om denne opgave", "reminder": "Administrer påmindelser om denne opgave",
"description": "Slå redigering af opgavebeskrivelse til/fra" "description": "Slå redigering af opgavebeskrivelse til/fra",
"delete": "Delete this task",
"priority": "Change the priority of this task",
"favorite": "Mark this task as favorite / unfavorite"
}, },
"project": { "project": {
"title": "Project Views", "title": "Project Views",
@ -907,9 +844,9 @@
"title": "Navigation", "title": "Navigation",
"overview": "Gå til oversigt", "overview": "Gå til oversigt",
"upcoming": "Gå til kommende opgaver", "upcoming": "Gå til kommende opgaver",
"namespaces": "Navigate to namespaces & projects",
"labels": "Naviger til etiketter", "labels": "Naviger til etiketter",
"teams": "Naviger til hold" "teams": "Naviger til hold",
"projects": "Navigate to projects"
} }
}, },
"update": { "update": {
@ -924,7 +861,8 @@
"unarchive": "Tilbagekald", "unarchive": "Tilbagekald",
"setBackground": "Indstil baggrund", "setBackground": "Indstil baggrund",
"share": "Del", "share": "Del",
"newProject": "New project" "newProject": "New project",
"createProject": "Create project"
}, },
"apiConfig": { "apiConfig": {
"url": "Vikunja URL", "url": "Vikunja URL",
@ -943,7 +881,7 @@
"notification": { "notification": {
"title": "Notifikationer", "title": "Notifikationer",
"none": "Du har ingen notifikationer. Hav en dejlig dag!", "none": "Du har ingen notifikationer. Hav en dejlig dag!",
"explainer": "Notifications will appear here when actions on namespaces, projects or tasks you subscribed to happen." "explainer": "Notifications will appear here when actions projects or tasks you subscribed to happen."
}, },
"quickActions": { "quickActions": {
"commands": "Kommandoer", "commands": "Kommandoer",
@ -954,14 +892,12 @@
"teams": "Hold", "teams": "Hold",
"newProject": "Enter the title of the new project…", "newProject": "Enter the title of the new project…",
"newTask": "Indtast titlen på den nye opgave…", "newTask": "Indtast titlen på den nye opgave…",
"newNamespace": "Indtast titlen på det nye navneområde…",
"newTeam": "Indtast navnet på det nye hold…", "newTeam": "Indtast navnet på det nye hold…",
"createTask": "Create a task in the current project ({title})", "createTask": "Create a task in the current project ({title})",
"createProject": "Create a project in the current namespace ({title})", "createProject": "Create a project in the current namespace ({title})",
"cmds": { "cmds": {
"newTask": "Ny Opgave", "newTask": "Ny Opgave",
"newProject": "New project", "newProject": "New project",
"newNamespace": "Nyt navneområde",
"newTeam": "Nyt hold" "newTeam": "Nyt hold"
} }
}, },
@ -1017,13 +953,6 @@
"4017": "Ugyldig komparator til opgavefilter.", "4017": "Ugyldig komparator til opgavefilter.",
"4018": "Ugyldig sammenkædning til opgavefilter.", "4018": "Ugyldig sammenkædning til opgavefilter.",
"4019": "Ugyldig værdi til opgavefilter.", "4019": "Ugyldig værdi til opgavefilter.",
"5001": "Navneområdet findes ikke.",
"5003": "Du har ikke adgang til det angivne navneområde.",
"5006": "Navneområdets navn må ikke være tomt.",
"5009": "Du skal have navneområde læseadgang for at udføre denne handling.",
"5010": "Dette hold har ikke adgang til dette navneområde.",
"5011": "Denne bruger har allerede adgang til dette navneområde.",
"5012": "Navneområdet er arkiveret og kan derfor kun læses.",
"6001": "Holdnavnet må ikke være tomt.", "6001": "Holdnavnet må ikke være tomt.",
"6002": "Holdet findes ikke.", "6002": "Holdet findes ikke.",
"6004": "The team already has access to that namespace or project.", "6004": "The team already has access to that namespace or project.",
@ -1053,4 +982,4 @@
"frontendVersion": "Frontend Version: {version}", "frontendVersion": "Frontend Version: {version}",
"apiVersion": "API Version: {version}" "apiVersion": "API Version: {version}"
} }
} }

View File

@ -6,9 +6,7 @@
"welcomeEvening": "Guten Abend, {username}!", "welcomeEvening": "Guten Abend, {username}!",
"lastViewed": "Zuletzt angesehen", "lastViewed": "Zuletzt angesehen",
"project": { "project": {
"newText": "Du kannst ein neues Projekt für deine neuen Aufgaben erstellen:", "importText": "Import your projects and tasks from other services into Vikunja:",
"new": "New project",
"importText": "Or import your projects and tasks from other services into Vikunja:",
"import": "Import your data into Vikunja" "import": "Import your data into Vikunja"
} }
}, },
@ -143,7 +141,7 @@
}, },
"deletion": { "deletion": {
"title": "Lösche deinen Vikunja-Account", "title": "Lösche deinen Vikunja-Account",
"text1": "The deletion of your account is permanent and cannot be undone. We will delete all your namespaces, projects, tasks and everything associated with it.", "text1": "The deletion of your account is permanent and cannot be undone. We will delete all your projects, tasks and everything associated with it.",
"text2": "Zum Fortfahren gib bitte dein Passwort ein. Du erhältst eine E-Mail mit weiteren Anweisungen.", "text2": "Zum Fortfahren gib bitte dein Passwort ein. Du erhältst eine E-Mail mit weiteren Anweisungen.",
"confirm": "Meinen Account löschen", "confirm": "Meinen Account löschen",
"requestSuccess": "Die Anfrage war erfolgreich. Du erhältst eine E-Mail mit weiteren Anweisungen.", "requestSuccess": "Die Anfrage war erfolgreich. Du erhältst eine E-Mail mit weiteren Anweisungen.",
@ -157,7 +155,7 @@
}, },
"export": { "export": {
"title": "Exportiere deine Vikunja-Daten", "title": "Exportiere deine Vikunja-Daten",
"description": "You can request a copy of all your Vikunja data. This include Namespaces, Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.", "description": "You can request a copy of all your Vikunja data. This includes Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
"descriptionPasswordRequired": "Bitte gib dein Passwort ein, um fortzufahren:", "descriptionPasswordRequired": "Bitte gib dein Passwort ein, um fortzufahren:",
"request": "Eine Kopie meiner Vikunja Daten anfordern", "request": "Eine Kopie meiner Vikunja Daten anfordern",
"success": "Du hast deine Daten bei Vikunja erfolgreich angefordert! Wir schicken dir eine E-Mail, sobald sie zum Download bereitstehen.", "success": "Du hast deine Daten bei Vikunja erfolgreich angefordert! Wir schicken dir eine E-Mail, sobald sie zum Download bereitstehen.",
@ -165,14 +163,18 @@
} }
}, },
"project": { "project": {
"archived": "This project is archived. It is not possible to create new or edit tasks for it.", "archivedMessage": "This project is archived. It is not possible to create new or edit tasks for it.",
"archived": "Archived",
"showArchived": "Show Archived",
"title": "Project Title", "title": "Project Title",
"color": "Color", "color": "Color",
"projects": "Projects", "projects": "Projects",
"parent": "Parent Project",
"search": "Type to search for a project…", "search": "Type to search for a project…",
"searchSelect": "Click or press enter to select this project", "searchSelect": "Click or press enter to select this project",
"shared": "Shared Projects", "shared": "Shared Projects",
"noDescriptionAvailable": "No project description is available.", "noDescriptionAvailable": "No project description is available.",
"inboxTitle": "Inbox",
"create": { "create": {
"header": "New project", "header": "New project",
"titlePlaceholder": "The project's title goes here…", "titlePlaceholder": "The project's title goes here…",
@ -210,7 +212,7 @@
"duplicate": { "duplicate": {
"title": "Duplicate this project", "title": "Duplicate this project",
"label": "Duplicate", "label": "Duplicate",
"text": "Select a namespace which should hold the duplicated project:", "text": "Select a parent project which should hold the duplicated project:",
"success": "The project was successfully duplicated." "success": "The project was successfully duplicated."
}, },
"edit": { "edit": {
@ -321,67 +323,6 @@
} }
} }
}, },
"namespace": {
"title": "Namespaces & Projects",
"namespace": "Namespace",
"showArchived": "Archivierte anzeigen",
"noneAvailable": "Du hast momentan keine Namespaces.",
"unarchive": "Archivierung aufheben",
"archived": "Archiviert",
"noProjects": "This namespace does not contain any projects.",
"createProject": "Create a new project in this namespace.",
"namespaces": "Namespaces",
"search": "Beginne zu schreiben, um einen Namespace zu suchen…",
"create": {
"title": "Neuer Namespace",
"titleRequired": "Bitte gebe einen Titel an.",
"explanation": "A namespace is a collection of projects you can share and use to organize your projects with. In fact, every project belongs to a namespace.",
"tooltip": "Was ist ein Namespace?",
"success": "Der Namespace wurde erfolgreich erstellt."
},
"archive": {
"titleArchive": "„{namespace}“ archivieren",
"titleUnarchive": "Archivierung von \"{namespace}\" aufheben",
"archiveText": "You won't be able to edit this namespace or create new projects until you un-archive it. This will also archive all projects in this namespace.",
"unarchiveText": "You will be able to create new projects or edit it.",
"success": "Der Namespace wurde erfolgreich archiviert.",
"unarchiveSuccess": "Der Namespace wurde erfolgreich wiederhergestellt.",
"description": "If a namespace is archived, you cannot create new projects or edit it."
},
"delete": {
"title": "„{namespace}“ löschen",
"text1": "Diesen Namespace mit sämtlichem Inhalt löschen?",
"text2": "This includes all projects and tasks and CANNOT BE UNDONE!",
"success": "Der Namespace wurde erfolgreich gelöscht."
},
"edit": {
"title": "„{namespace}“ bearbeiten",
"success": "Der Namespace wurde erfolgreich aktualisiert."
},
"share": {
"title": "„{namespace}“ teilen"
},
"attributes": {
"title": "Namespace Titel",
"titlePlaceholder": "Titel des Namespace angeben…",
"description": "Beschreibung",
"descriptionPlaceholder": "Beschreibung für den Namespace eingeben…",
"color": "Farbe",
"archived": "Ist archiviert",
"isArchived": "Dieser Namespace ist archiviert"
},
"pseudo": {
"sharedProjects": {
"title": "Shared Projects"
},
"favorites": {
"title": "Favoriten"
},
"savedFilters": {
"title": "Filter"
}
}
},
"filters": { "filters": {
"title": "Filter", "title": "Filter",
"clear": "Filter zurücksetzen", "clear": "Filter zurücksetzen",
@ -403,7 +344,7 @@
}, },
"create": { "create": {
"title": "Neuer gespeicherter Filter", "title": "Neuer gespeicherter Filter",
"description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed. Once created, it will appear in a special namespace.", "description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed.",
"action": "Neuen gespeicherten Filter erstellen", "action": "Neuen gespeicherten Filter erstellen",
"titleRequired": "Bitte gib den Titel für den Filter an." "titleRequired": "Bitte gib den Titel für den Filter an."
}, },
@ -674,19 +615,13 @@
"updated": "Aktualisiert" "updated": "Aktualisiert"
}, },
"subscription": { "subscription": {
"subscribedProjectThroughParentNamespace": "You can't unsubscribe here because you are subscribed to this project through its namespace.",
"subscribedTaskThroughParentNamespace": "Du kannst hier nicht de-abonnieren, da du diese Aufgabe über ihren Namespace abonniert hast.",
"subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.", "subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.",
"subscribedNamespace": "Du hast diesen Namespace abonniert und erhältst Benachrichtigungen über Änderungen.",
"notSubscribedNamespace": "Du hast diesen Namespace nicht abonniert und erhältst keine Benachrichtigungen über Änderungen.",
"subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.", "subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.",
"notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.", "notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.",
"subscribedTask": "Du hast diese Aufgabe abonniert und erhältst Benachrichtigungen über Änderungen.", "subscribedTask": "Du hast diese Aufgabe abonniert und erhältst Benachrichtigungen über Änderungen.",
"notSubscribedTask": "Du hast diese Aufgabe nicht abonniert und erhältst keine Benachrichtigungen über Änderungen.", "notSubscribedTask": "Du hast diese Aufgabe nicht abonniert und erhältst keine Benachrichtigungen über Änderungen.",
"subscribe": "Abonnieren", "subscribe": "Abonnieren",
"unsubscribe": "Abbestellen", "unsubscribe": "Abbestellen",
"subscribeSuccessNamespace": "Du hast diesen Namespace jetzt abonniert",
"unsubscribeSuccessNamespace": "Du hast diesen Namespace jetzt nicht mehr abonniert",
"subscribeSuccessProject": "You are now subscribed to this project", "subscribeSuccessProject": "You are now subscribed to this project",
"unsubscribeSuccessProject": "You are now unsubscribed to this project", "unsubscribeSuccessProject": "You are now unsubscribed to this project",
"subscribeSuccessTask": "Du hast diese Aufgabe jetzt abonniert", "subscribeSuccessTask": "Du hast diese Aufgabe jetzt abonniert",
@ -763,7 +698,6 @@
"searchPlaceholder": "Beginne zu schreiben, um eine Aufgabe zu suchen, die als Beziehung hinzugefügt werden soll…", "searchPlaceholder": "Beginne zu schreiben, um eine Aufgabe zu suchen, die als Beziehung hinzugefügt werden soll…",
"createPlaceholder": "Füge diese Aufgabe als neue Aufgabenbeziehung hinzu", "createPlaceholder": "Füge diese Aufgabe als neue Aufgabenbeziehung hinzu",
"differentProject": "This task belongs to a different project.", "differentProject": "This task belongs to a different project.",
"differentNamespace": "Diese Aufgabe gehört zu einem anderen Namespace.",
"noneYet": "Keine Aufgabenbeziehung vorhanden.", "noneYet": "Keine Aufgabenbeziehung vorhanden.",
"delete": "Aufgabenbeziehung entfernen", "delete": "Aufgabenbeziehung entfernen",
"deleteText1": "Willst du diese Aufgabenbeziehung wirklich entfernen?", "deleteText1": "Willst du diese Aufgabenbeziehung wirklich entfernen?",
@ -848,19 +782,19 @@
"delete": { "delete": {
"header": "Team löschen", "header": "Team löschen",
"text1": "Bist du sicher, dass du dieses Team und alle seine Mitglieder löschen willst?", "text1": "Bist du sicher, dass du dieses Team und alle seine Mitglieder löschen willst?",
"text2": "All team members will lose access to projects and namespaces shared with this team. This CANNOT BE UNDONE!", "text2": "All team members will lose access to projects shared with this team. This CANNOT BE UNDONE!",
"success": "Das Team wurde erfolgreich gelöscht." "success": "Das Team wurde erfolgreich gelöscht."
}, },
"deleteUser": { "deleteUser": {
"header": "Benutzer:innen aus dem Team entfernen", "header": "Benutzer:innen aus dem Team entfernen",
"text1": "Bist du sicher, dass du diese:n Benutzer:in aus dem Team entfernen willst?", "text1": "Bist du sicher, dass du diese:n Benutzer:in aus dem Team entfernen willst?",
"text2": "They will lose access to all projects and namespaces this team has access to. This CANNOT BE UNDONE!", "text2": "They will lose access to all projects this team has access to. This CANNOT BE UNDONE!",
"success": "Der:die Benutzer:in wurde erfolgreich aus dem Team gelöscht." "success": "Der:die Benutzer:in wurde erfolgreich aus dem Team gelöscht."
}, },
"leave": { "leave": {
"title": "Team verlassen", "title": "Team verlassen",
"text1": "Bist du sicher, dass du dieses Team verlassen willst?", "text1": "Bist du sicher, dass du dieses Team verlassen willst?",
"text2": "You will lose access to all projects and namespaces this team has access to. If you change your mind you'll need a team admin to add you again.", "text2": "You will lose access to all projects this team has access to. If you change your mind you'll need a team admin to add you again.",
"success": "Du hast das Team erfolgreich verlassen." "success": "Du hast das Team erfolgreich verlassen."
} }
}, },
@ -894,7 +828,10 @@
"color": "Die Farbe dieser Aufgabe ändern", "color": "Die Farbe dieser Aufgabe ändern",
"move": "Move this task to another project", "move": "Move this task to another project",
"reminder": "Erinnerungen für diese Aufgabe verwalten", "reminder": "Erinnerungen für diese Aufgabe verwalten",
"description": "Aufgabenbeschreibung bearbeiten" "description": "Aufgabenbeschreibung bearbeiten",
"delete": "Delete this task",
"priority": "Change the priority of this task",
"favorite": "Mark this task as favorite / unfavorite"
}, },
"project": { "project": {
"title": "Project Views", "title": "Project Views",
@ -907,9 +844,9 @@
"title": "Navigation", "title": "Navigation",
"overview": "Die Startseite aufrufen", "overview": "Die Startseite aufrufen",
"upcoming": "Anstehende Aufgaben aufrufen", "upcoming": "Anstehende Aufgaben aufrufen",
"namespaces": "Navigate to namespaces & projects",
"labels": "Labels aufrufen", "labels": "Labels aufrufen",
"teams": "Teams aufrufen" "teams": "Teams aufrufen",
"projects": "Navigate to projects"
} }
}, },
"update": { "update": {
@ -924,7 +861,8 @@
"unarchive": "Archivierung aufheben", "unarchive": "Archivierung aufheben",
"setBackground": "Hintergrund einstellen", "setBackground": "Hintergrund einstellen",
"share": "Teilen", "share": "Teilen",
"newProject": "New project" "newProject": "New project",
"createProject": "Create project"
}, },
"apiConfig": { "apiConfig": {
"url": "Vikunja-URL", "url": "Vikunja-URL",
@ -943,7 +881,7 @@
"notification": { "notification": {
"title": "Benachrichtigungen", "title": "Benachrichtigungen",
"none": "Du hast keine Benachrichtigungen. Einen schönen Tag noch!", "none": "Du hast keine Benachrichtigungen. Einen schönen Tag noch!",
"explainer": "Notifications will appear here when actions on namespaces, projects or tasks you subscribed to happen." "explainer": "Notifications will appear here when actions projects or tasks you subscribed to happen."
}, },
"quickActions": { "quickActions": {
"commands": "Befehle", "commands": "Befehle",
@ -954,14 +892,12 @@
"teams": "Teams", "teams": "Teams",
"newProject": "Enter the title of the new project…", "newProject": "Enter the title of the new project…",
"newTask": "Gib den Titel der neuen Aufgabe ein …", "newTask": "Gib den Titel der neuen Aufgabe ein …",
"newNamespace": "Gib den Titel des neuen Namespaces ein…",
"newTeam": "Gib den Namen des neuen Teams ein …", "newTeam": "Gib den Namen des neuen Teams ein …",
"createTask": "Create a task in the current project ({title})", "createTask": "Create a task in the current project ({title})",
"createProject": "Create a project in the current namespace ({title})", "createProject": "Create a project",
"cmds": { "cmds": {
"newTask": "Neue Aufgabe", "newTask": "Neue Aufgabe",
"newProject": "New project", "newProject": "New project",
"newNamespace": "Neuer Namespace",
"newTeam": "Neues Team" "newTeam": "Neues Team"
} }
}, },
@ -1017,16 +953,9 @@
"4017": "Ungültiger Aufgabenfilter (Vergleichskriterium).", "4017": "Ungültiger Aufgabenfilter (Vergleichskriterium).",
"4018": "Ungültige Verkettung von Aufgabenfiltern.", "4018": "Ungültige Verkettung von Aufgabenfiltern.",
"4019": "Ungültiger Aufgabenfilter (Wert).", "4019": "Ungültiger Aufgabenfilter (Wert).",
"5001": "Dieser Namespace existiert nicht.",
"5003": "Du hast keinen Zugriff auf den Namespace.",
"5006": "Der Namespace Titel kann nicht leer sein.",
"5009": "Du benötigst Leserechte in diesem Namespace, um diese Aktion durchzuführen.",
"5010": "Dieses Team hat keinen Zugriff auf diesen Namespace.",
"5011": "Diese:r Benutzer:in hat bereits Zugriff auf diesen Namespace.",
"5012": "Dieser Namespace ist archiviert und kann deshalb nur gelesen werden.",
"6001": "Der Teamname kann nicht leer sein.", "6001": "Der Teamname kann nicht leer sein.",
"6002": "Das Team existiert nicht.", "6002": "Das Team existiert nicht.",
"6004": "The team already has access to that namespace or project.", "6004": "The team already has access to that project.",
"6005": "Diese:r Benutzer:in ist bereits dem Team beigetreten.", "6005": "Diese:r Benutzer:in ist bereits dem Team beigetreten.",
"6006": "Du kannst den:die letzten Benutzer:in dieses Teams nicht löschen.", "6006": "Du kannst den:die letzten Benutzer:in dieses Teams nicht löschen.",
"6007": "The team does not have access to the project to perform that action.", "6007": "The team does not have access to the project to perform that action.",
@ -1053,4 +982,4 @@
"frontendVersion": "Frontend-Version: {version}", "frontendVersion": "Frontend-Version: {version}",
"apiVersion": "API-Version: {version}" "apiVersion": "API-Version: {version}"
} }
} }

View File

@ -6,9 +6,7 @@
"welcomeEvening": "Guten Abend, {username}!", "welcomeEvening": "Guten Abend, {username}!",
"lastViewed": "Zletscht ahglueget", "lastViewed": "Zletscht ahglueget",
"project": { "project": {
"newText": "Du kannst ein neues Projekt für deine neuen Aufgaben erstellen:", "importText": "Import your projects and tasks from other services into Vikunja:",
"new": "New project",
"importText": "Or import your projects and tasks from other services into Vikunja:",
"import": "Import your data into Vikunja" "import": "Import your data into Vikunja"
} }
}, },
@ -143,7 +141,7 @@
}, },
"deletion": { "deletion": {
"title": "Lösche deinen Vikunja-Account", "title": "Lösche deinen Vikunja-Account",
"text1": "The deletion of your account is permanent and cannot be undone. We will delete all your namespaces, projects, tasks and everything associated with it.", "text1": "The deletion of your account is permanent and cannot be undone. We will delete all your projects, tasks and everything associated with it.",
"text2": "Zum Fortfahren gib bitte dein Passwort ein. Du erhältst eine E-Mail mit weiteren Anweisungen.", "text2": "Zum Fortfahren gib bitte dein Passwort ein. Du erhältst eine E-Mail mit weiteren Anweisungen.",
"confirm": "Meinen Account löschen", "confirm": "Meinen Account löschen",
"requestSuccess": "Die Anfrage war erfolgreich. Du erhältst eine E-Mail mit weiteren Anweisungen.", "requestSuccess": "Die Anfrage war erfolgreich. Du erhältst eine E-Mail mit weiteren Anweisungen.",
@ -157,7 +155,7 @@
}, },
"export": { "export": {
"title": "Exportiere deine Vikunja-Daten", "title": "Exportiere deine Vikunja-Daten",
"description": "You can request a copy of all your Vikunja data. This include Namespaces, Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.", "description": "You can request a copy of all your Vikunja data. This includes Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
"descriptionPasswordRequired": "Bitte gib dein Passwort ein, um fortzufahren:", "descriptionPasswordRequired": "Bitte gib dein Passwort ein, um fortzufahren:",
"request": "Eine Kopie meiner Vikunja Daten anfordern", "request": "Eine Kopie meiner Vikunja Daten anfordern",
"success": "Du hast deine Daten bei Vikunja erfolgreich angefordert! Wir schicken dir eine E-Mail, sobald sie zum Download bereitstehen.", "success": "Du hast deine Daten bei Vikunja erfolgreich angefordert! Wir schicken dir eine E-Mail, sobald sie zum Download bereitstehen.",
@ -165,14 +163,18 @@
} }
}, },
"project": { "project": {
"archived": "This project is archived. It is not possible to create new or edit tasks for it.", "archivedMessage": "This project is archived. It is not possible to create new or edit tasks for it.",
"archived": "Archived",
"showArchived": "Show Archived",
"title": "Project Title", "title": "Project Title",
"color": "Color", "color": "Color",
"projects": "Projects", "projects": "Projects",
"parent": "Parent Project",
"search": "Type to search for a project…", "search": "Type to search for a project…",
"searchSelect": "Click or press enter to select this project", "searchSelect": "Click or press enter to select this project",
"shared": "Shared Projects", "shared": "Shared Projects",
"noDescriptionAvailable": "No project description is available.", "noDescriptionAvailable": "No project description is available.",
"inboxTitle": "Inbox",
"create": { "create": {
"header": "New project", "header": "New project",
"titlePlaceholder": "The project's title goes here…", "titlePlaceholder": "The project's title goes here…",
@ -210,7 +212,7 @@
"duplicate": { "duplicate": {
"title": "Duplicate this project", "title": "Duplicate this project",
"label": "Duplicate", "label": "Duplicate",
"text": "Select a namespace which should hold the duplicated project:", "text": "Select a parent project which should hold the duplicated project:",
"success": "The project was successfully duplicated." "success": "The project was successfully duplicated."
}, },
"edit": { "edit": {
@ -321,67 +323,6 @@
} }
} }
}, },
"namespace": {
"title": "Namespaces & Projects",
"namespace": "Namensruum",
"showArchived": "Archivierti aahzeige",
"noneAvailable": "Du hesch momentan kein Namensruuim.",
"unarchive": "Ent-archiviere",
"archived": "Archiviert",
"noProjects": "This namespace does not contain any projects.",
"createProject": "Create a new project in this namespace.",
"namespaces": "Namensrüüm",
"search": "Schriib, um nachemne Namensruum z'sueche…",
"create": {
"title": "Neuer Namespace",
"titleRequired": "Bitte gib en Titl ah.",
"explanation": "A namespace is a collection of projects you can share and use to organize your projects with. In fact, every project belongs to a namespace.",
"tooltip": "Was isch en Namensruum?",
"success": "Namensruum erstellt."
},
"archive": {
"titleArchive": "\"{namespace}\" archiviere",
"titleUnarchive": "\"{namespace}\" ent-archiviere",
"archiveText": "You won't be able to edit this namespace or create new projects until you un-archive it. This will also archive all projects in this namespace.",
"unarchiveText": "You will be able to create new projects or edit it.",
"success": "De Namensruum isch erfolgriich archiviert worde.",
"unarchiveSuccess": "Der Namespace wurde erfolgreich wiederhergestellt.",
"description": "If a namespace is archived, you cannot create new projects or edit it."
},
"delete": {
"title": "\"{namespace}\" chüble",
"text1": "Bisch du dir sicher, dass du de Namensruum und all ihren Inhalt chüble wetsch?",
"text2": "This includes all projects and tasks and CANNOT BE UNDONE!",
"success": "Namensruum g'chüblet."
},
"edit": {
"title": "\"{namespace}\" bearbeite",
"success": "Namensruum aktualisiert."
},
"share": {
"title": "\"{namespace}\" teile"
},
"attributes": {
"title": "Namensruumtitl",
"titlePlaceholder": "De Namensruumtitl chunt da ahne…",
"description": "Beschriibig",
"descriptionPlaceholder": "D'Namensruum Beschriibig chunt da ahne…",
"color": "Farb",
"archived": "Isch archiviert",
"isArchived": "De Namensruum isch archiviert"
},
"pseudo": {
"sharedProjects": {
"title": "Shared Projects"
},
"favorites": {
"title": "Favorite"
},
"savedFilters": {
"title": "Filter"
}
}
},
"filters": { "filters": {
"title": "Filter", "title": "Filter",
"clear": "Filter zurücksetzen", "clear": "Filter zurücksetzen",
@ -403,7 +344,7 @@
}, },
"create": { "create": {
"title": "Neuer gespeicherter Filter", "title": "Neuer gespeicherter Filter",
"description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed. Once created, it will appear in a special namespace.", "description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed.",
"action": "Neue gspeicherete Filter erstelle", "action": "Neue gspeicherete Filter erstelle",
"titleRequired": "Bitte gib den Titel für den Filter an." "titleRequired": "Bitte gib den Titel für den Filter an."
}, },
@ -674,19 +615,13 @@
"updated": "Aktualisiert" "updated": "Aktualisiert"
}, },
"subscription": { "subscription": {
"subscribedProjectThroughParentNamespace": "You can't unsubscribe here because you are subscribed to this project through its namespace.",
"subscribedTaskThroughParentNamespace": "Du kannst hier nicht de-abonnieren, da du diese Aufgabe über ihren Namespace abonniert hast.",
"subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.", "subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.",
"subscribedNamespace": "Du hast diesen Namespace abonniert und erhältst Benachrichtigungen über Änderungen.",
"notSubscribedNamespace": "Du hast diesen Namespace nicht abonniert und erhältst keine Benachrichtigungen über Änderungen.",
"subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.", "subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.",
"notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.", "notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.",
"subscribedTask": "Du hast diese Aufgabe abonniert und erhältst Benachrichtigungen über Änderungen.", "subscribedTask": "Du hast diese Aufgabe abonniert und erhältst Benachrichtigungen über Änderungen.",
"notSubscribedTask": "Du hast diese Aufgabe nicht abonniert und erhältst keine Benachrichtigungen über Änderungen.", "notSubscribedTask": "Du hast diese Aufgabe nicht abonniert und erhältst keine Benachrichtigungen über Änderungen.",
"subscribe": "Abooniere", "subscribe": "Abooniere",
"unsubscribe": "Deabonniere", "unsubscribe": "Deabonniere",
"subscribeSuccessNamespace": "Du hast diesen Namespace jetzt abonniert",
"unsubscribeSuccessNamespace": "Du hast diesen Namespace jetzt nicht mehr abonniert",
"subscribeSuccessProject": "You are now subscribed to this project", "subscribeSuccessProject": "You are now subscribed to this project",
"unsubscribeSuccessProject": "You are now unsubscribed to this project", "unsubscribeSuccessProject": "You are now unsubscribed to this project",
"subscribeSuccessTask": "Du hast diese Aufgabe jetzt abonniert", "subscribeSuccessTask": "Du hast diese Aufgabe jetzt abonniert",
@ -763,7 +698,6 @@
"searchPlaceholder": "Schriib, um e neui Uufgab als Zueghörigkeit hinzuezfüege…", "searchPlaceholder": "Schriib, um e neui Uufgab als Zueghörigkeit hinzuezfüege…",
"createPlaceholder": "Das als en neui Zueghörigkeit hinzuefüege", "createPlaceholder": "Das als en neui Zueghörigkeit hinzuefüege",
"differentProject": "This task belongs to a different project.", "differentProject": "This task belongs to a different project.",
"differentNamespace": "Diese Aufgabe gehört zu einem anderen Namespace.",
"noneYet": "S'git kei Uufgabe Beziehige.", "noneYet": "S'git kei Uufgabe Beziehige.",
"delete": "Uufgabe Beziehig chüble", "delete": "Uufgabe Beziehig chüble",
"deleteText1": "Bisch du dir sicher, dass du die Zueghörigkeit chüblä wetsch?", "deleteText1": "Bisch du dir sicher, dass du die Zueghörigkeit chüblä wetsch?",
@ -848,19 +782,19 @@
"delete": { "delete": {
"header": "Das Team chüble", "header": "Das Team chüble",
"text1": "Bischder sicher, dasst wetsch da Team mit allne Mitglieder lösche?", "text1": "Bischder sicher, dasst wetsch da Team mit allne Mitglieder lösche?",
"text2": "All team members will lose access to projects and namespaces shared with this team. This CANNOT BE UNDONE!", "text2": "All team members will lose access to projects shared with this team. This CANNOT BE UNDONE!",
"success": "Da Team isch erfolgriich g'chüblet wore." "success": "Da Team isch erfolgriich g'chüblet wore."
}, },
"deleteUser": { "deleteUser": {
"header": "Benutzer usem Team entferne", "header": "Benutzer usem Team entferne",
"text1": "Bisch du dir sicher, dass du de Benutzer usm Team werfe wetsch?", "text1": "Bisch du dir sicher, dass du de Benutzer usm Team werfe wetsch?",
"text2": "They will lose access to all projects and namespaces this team has access to. This CANNOT BE UNDONE!", "text2": "They will lose access to all projects this team has access to. This CANNOT BE UNDONE!",
"success": "Benutzer erfolgriich usegworfe." "success": "Benutzer erfolgriich usegworfe."
}, },
"leave": { "leave": {
"title": "Team verlassen", "title": "Team verlassen",
"text1": "Bist du sicher, dass du dieses Team verlassen willst?", "text1": "Bist du sicher, dass du dieses Team verlassen willst?",
"text2": "You will lose access to all projects and namespaces this team has access to. If you change your mind you'll need a team admin to add you again.", "text2": "You will lose access to all projects this team has access to. If you change your mind you'll need a team admin to add you again.",
"success": "Du hast das Team erfolgreich verlassen." "success": "Du hast das Team erfolgreich verlassen."
} }
}, },
@ -894,7 +828,10 @@
"color": "Die Farbe dieser Aufgabe ändern", "color": "Die Farbe dieser Aufgabe ändern",
"move": "Move this task to another project", "move": "Move this task to another project",
"reminder": "Erinnerungen für diese Aufgabe verwalten", "reminder": "Erinnerungen für diese Aufgabe verwalten",
"description": "Aufgabenbeschreibung bearbeiten" "description": "Aufgabenbeschreibung bearbeiten",
"delete": "Delete this task",
"priority": "Change the priority of this task",
"favorite": "Mark this task as favorite / unfavorite"
}, },
"project": { "project": {
"title": "Project Views", "title": "Project Views",
@ -907,9 +844,9 @@
"title": "Navigation", "title": "Navigation",
"overview": "Die Startseite aufrufen", "overview": "Die Startseite aufrufen",
"upcoming": "Anstehende Aufgaben aufrufen", "upcoming": "Anstehende Aufgaben aufrufen",
"namespaces": "Navigate to namespaces & projects",
"labels": "Labels aufrufen", "labels": "Labels aufrufen",
"teams": "Teams aufrufen" "teams": "Teams aufrufen",
"projects": "Navigate to projects"
} }
}, },
"update": { "update": {
@ -924,7 +861,8 @@
"unarchive": "Ent-archiviere", "unarchive": "Ent-archiviere",
"setBackground": "Hintergrund iihstelle", "setBackground": "Hintergrund iihstelle",
"share": "Teilä", "share": "Teilä",
"newProject": "New project" "newProject": "New project",
"createProject": "Create project"
}, },
"apiConfig": { "apiConfig": {
"url": "Vikunja URL", "url": "Vikunja URL",
@ -943,7 +881,7 @@
"notification": { "notification": {
"title": "Benachrichtigunge", "title": "Benachrichtigunge",
"none": "Du hesch kei neui Benachrichtunge. Heb e schös Tägli!", "none": "Du hesch kei neui Benachrichtunge. Heb e schös Tägli!",
"explainer": "Notifications will appear here when actions on namespaces, projects or tasks you subscribed to happen." "explainer": "Notifications will appear here when actions projects or tasks you subscribed to happen."
}, },
"quickActions": { "quickActions": {
"commands": "Befehl", "commands": "Befehl",
@ -954,14 +892,12 @@
"teams": "Teams", "teams": "Teams",
"newProject": "Enter the title of the new project…", "newProject": "Enter the title of the new project…",
"newTask": "Gib en Titl für die neu Uufgab iih…", "newTask": "Gib en Titl für die neu Uufgab iih…",
"newNamespace": "Gib en Titl für de neu Namensruum iih…",
"newTeam": "Gib en Name für da neui Team iih…", "newTeam": "Gib en Name für da neui Team iih…",
"createTask": "Create a task in the current project ({title})", "createTask": "Create a task in the current project ({title})",
"createProject": "Create a project in the current namespace ({title})", "createProject": "Create a project",
"cmds": { "cmds": {
"newTask": "Neui Uufgab", "newTask": "Neui Uufgab",
"newProject": "New project", "newProject": "New project",
"newNamespace": "Neue Namensruum",
"newTeam": "Neus Team" "newTeam": "Neus Team"
} }
}, },
@ -1017,16 +953,9 @@
"4017": "Ungültige Uufgabefilter vergliich.", "4017": "Ungültige Uufgabefilter vergliich.",
"4018": "Ungültige Verkettung von Aufgabenfiltern.", "4018": "Ungültige Verkettung von Aufgabenfiltern.",
"4019": "Ungültigi Uufgabe Filter Wert.", "4019": "Ungültigi Uufgabe Filter Wert.",
"5001": "De Namensruum existiert nid.",
"5003": "Du hesch kei Zuegriff zu dem Namensruum.",
"5006": "De Namensruum Name cha nid leer sii.",
"5009": "Du bruuchsch Läsezuegriff uf de Namensruum, um das durezfüehre.",
"5010": "Da Team hett kei zuegriff uf de Namensruum.",
"5011": "De Benutzer hett bereits zuegriff uf de Namensruum.",
"5012": "De Namensruum isch momentan schriibgschützt weil er archiviert isch.",
"6001": "Der Teamname kann nicht leer sein.", "6001": "Der Teamname kann nicht leer sein.",
"6002": "Da Team giz nid.", "6002": "Da Team giz nid.",
"6004": "The team already has access to that namespace or project.", "6004": "The team already has access to that project.",
"6005": "De Benutzer isch scho bi dem Team.", "6005": "De Benutzer isch scho bi dem Team.",
"6006": "Du chasch nid de letschti Benutzer vom Team lösche.", "6006": "Du chasch nid de letschti Benutzer vom Team lösche.",
"6007": "The team does not have access to the project to perform that action.", "6007": "The team does not have access to the project to perform that action.",
@ -1053,4 +982,4 @@
"frontendVersion": "Frontend Version: {version}", "frontendVersion": "Frontend Version: {version}",
"apiVersion": "API Version: {version}" "apiVersion": "API Version: {version}"
} }
} }

View File

@ -6,9 +6,7 @@
"welcomeEvening": "Good Evening {username}!", "welcomeEvening": "Good Evening {username}!",
"lastViewed": "Last viewed", "lastViewed": "Last viewed",
"project": { "project": {
"newText": "You can create a new project for your new tasks:", "importText": "Import your projects and tasks from other services into Vikunja:",
"new": "New project",
"importText": "Or import your projects and tasks from other services into Vikunja:",
"import": "Import your data into Vikunja" "import": "Import your data into Vikunja"
} }
}, },
@ -143,7 +141,7 @@
}, },
"deletion": { "deletion": {
"title": "Delete your Vikunja Account", "title": "Delete your Vikunja Account",
"text1": "The deletion of your account is permanent and cannot be undone. We will delete all your namespaces, projects, tasks and everything associated with it.", "text1": "The deletion of your account is permanent and cannot be undone. We will delete all your projects, tasks and everything associated with it.",
"text2": "To proceed, please enter your password. You will receive an email with further instructions.", "text2": "To proceed, please enter your password. You will receive an email with further instructions.",
"confirm": "Delete my account", "confirm": "Delete my account",
"requestSuccess": "The request was successful. You'll receive an email with further instructions.", "requestSuccess": "The request was successful. You'll receive an email with further instructions.",
@ -157,7 +155,7 @@
}, },
"export": { "export": {
"title": "Export your Vikunja data", "title": "Export your Vikunja data",
"description": "You can request a copy of all your Vikunja data. This include Namespaces, Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.", "description": "You can request a copy of all your Vikunja data. This includes Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
"descriptionPasswordRequired": "Please enter your password to proceed:", "descriptionPasswordRequired": "Please enter your password to proceed:",
"request": "Request a copy of my Vikunja Data", "request": "Request a copy of my Vikunja Data",
"success": "You've successfully requested your Vikunja Data! We will send you an email once it's ready to download.", "success": "You've successfully requested your Vikunja Data! We will send you an email once it's ready to download.",
@ -165,14 +163,18 @@
} }
}, },
"project": { "project": {
"archived": "This project is archived. It is not possible to create new or edit tasks for it.", "archivedMessage": "This project is archived. It is not possible to create new or edit tasks for it.",
"archived": "Archived",
"showArchived": "Show Archived",
"title": "Project Title", "title": "Project Title",
"color": "Color", "color": "Color",
"projects": "Projects", "projects": "Projects",
"parent": "Parent Project",
"search": "Type to search for a project…", "search": "Type to search for a project…",
"searchSelect": "Click or press enter to select this project", "searchSelect": "Click or press enter to select this project",
"shared": "Shared Projects", "shared": "Shared Projects",
"noDescriptionAvailable": "No project description is available.", "noDescriptionAvailable": "No project description is available.",
"inboxTitle": "Inbox",
"create": { "create": {
"header": "New project", "header": "New project",
"titlePlaceholder": "The project's title goes here…", "titlePlaceholder": "The project's title goes here…",
@ -210,7 +212,7 @@
"duplicate": { "duplicate": {
"title": "Duplicate this project", "title": "Duplicate this project",
"label": "Duplicate", "label": "Duplicate",
"text": "Select a namespace which should hold the duplicated project:", "text": "Select a parent project which should hold the duplicated project:",
"success": "The project was successfully duplicated." "success": "The project was successfully duplicated."
}, },
"edit": { "edit": {
@ -321,67 +323,6 @@
} }
} }
}, },
"namespace": {
"title": "Namespaces & Projects",
"namespace": "Namespace",
"showArchived": "Show Archived",
"noneAvailable": "You don't have any namespaces right now.",
"unarchive": "Un-Archive",
"archived": "Archived",
"noProjects": "This namespace does not contain any projects.",
"createProject": "Create a new project in this namespace.",
"namespaces": "Namespaces",
"search": "Type to search for a namespace…",
"create": {
"title": "New namespace",
"titleRequired": "Please specify a title.",
"explanation": "A namespace is a collection of projects you can share and use to organize your projects with. In fact, every project belongs to a namespace.",
"tooltip": "What's a namespace?",
"success": "The namespace was successfully created."
},
"archive": {
"titleArchive": "Archive \"{namespace}\"",
"titleUnarchive": "Un-Archive \"{namespace}\"",
"archiveText": "You won't be able to edit this namespace or create new projects until you un-archive it. This will also archive all projects in this namespace.",
"unarchiveText": "You will be able to create new projects or edit it.",
"success": "The namespace was successfully archived.",
"unarchiveSuccess": "The namespace was successfully un-archived.",
"description": "If a namespace is archived, you cannot create new projects or edit it."
},
"delete": {
"title": "Delete \"{namespace}\"",
"text1": "Are you sure you want to delete this namespace and all of its contents?",
"text2": "This includes all projects and tasks and CANNOT BE UNDONE!",
"success": "The namespace was successfully deleted."
},
"edit": {
"title": "Edit \"{namespace}\"",
"success": "The namespace was successfully updated."
},
"share": {
"title": "Share \"{namespace}\""
},
"attributes": {
"title": "Namespace Title",
"titlePlaceholder": "The namespace title goes here…",
"description": "Description",
"descriptionPlaceholder": "The namespaces description goes here…",
"color": "Color",
"archived": "Is Archived",
"isArchived": "This namespace is archived"
},
"pseudo": {
"sharedProjects": {
"title": "Shared Projects"
},
"favorites": {
"title": "Favorites"
},
"savedFilters": {
"title": "Filters"
}
}
},
"filters": { "filters": {
"title": "Filters", "title": "Filters",
"clear": "Clear Filters", "clear": "Clear Filters",
@ -403,7 +344,7 @@
}, },
"create": { "create": {
"title": "New Saved Filter", "title": "New Saved Filter",
"description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed. Once created, it will appear in a special namespace.", "description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed.",
"action": "Create new saved filter", "action": "Create new saved filter",
"titleRequired": "Please provide a title for the filter." "titleRequired": "Please provide a title for the filter."
}, },
@ -677,19 +618,13 @@
"updated": "Updated" "updated": "Updated"
}, },
"subscription": { "subscription": {
"subscribedProjectThroughParentNamespace": "You can't unsubscribe here because you are subscribed to this project through its namespace.",
"subscribedTaskThroughParentNamespace": "You can't unsubscribe here because you are subscribed to this task through its namespace.",
"subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.", "subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.",
"subscribedNamespace": "You are currently subscribed to this namespace and will receive notifications for changes.",
"notSubscribedNamespace": "You are not subscribed to this namespace and won't receive notifications for changes.",
"subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.", "subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.",
"notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.", "notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.",
"subscribedTask": "You are currently subscribed to this task and will receive notifications for changes.", "subscribedTask": "You are currently subscribed to this task and will receive notifications for changes.",
"notSubscribedTask": "You are not subscribed to this task and won't receive notifications for changes.", "notSubscribedTask": "You are not subscribed to this task and won't receive notifications for changes.",
"subscribe": "Subscribe", "subscribe": "Subscribe",
"unsubscribe": "Unsubscribe", "unsubscribe": "Unsubscribe",
"subscribeSuccessNamespace": "You are now subscribed to this namespace",
"unsubscribeSuccessNamespace": "You are now unsubscribed to this namespace",
"subscribeSuccessProject": "You are now subscribed to this project", "subscribeSuccessProject": "You are now subscribed to this project",
"unsubscribeSuccessProject": "You are now unsubscribed to this project", "unsubscribeSuccessProject": "You are now unsubscribed to this project",
"subscribeSuccessTask": "You are now subscribed to this task", "subscribeSuccessTask": "You are now subscribed to this task",
@ -766,7 +701,6 @@
"searchPlaceholder": "Type search for a new task to add as related…", "searchPlaceholder": "Type search for a new task to add as related…",
"createPlaceholder": "Add this as new related task", "createPlaceholder": "Add this as new related task",
"differentProject": "This task belongs to a different project.", "differentProject": "This task belongs to a different project.",
"differentNamespace": "This task belongs to a different namespace.",
"noneYet": "No task relations yet.", "noneYet": "No task relations yet.",
"delete": "Delete Task Relation", "delete": "Delete Task Relation",
"deleteText1": "Are you sure you want to delete this task relation?", "deleteText1": "Are you sure you want to delete this task relation?",
@ -851,19 +785,19 @@
"delete": { "delete": {
"header": "Delete the team", "header": "Delete the team",
"text1": "Are you sure you want to delete this team and all of its members?", "text1": "Are you sure you want to delete this team and all of its members?",
"text2": "All team members will lose access to projects and namespaces shared with this team. This CANNOT BE UNDONE!", "text2": "All team members will lose access to projects shared with this team. This CANNOT BE UNDONE!",
"success": "The team was successfully deleted." "success": "The team was successfully deleted."
}, },
"deleteUser": { "deleteUser": {
"header": "Remove a user from the team", "header": "Remove a user from the team",
"text1": "Are you sure you want to remove this user from the team?", "text1": "Are you sure you want to remove this user from the team?",
"text2": "They will lose access to all projects and namespaces this team has access to. This CANNOT BE UNDONE!", "text2": "They will lose access to all projects this team has access to. This CANNOT BE UNDONE!",
"success": "The user was successfully deleted from the team." "success": "The user was successfully deleted from the team."
}, },
"leave": { "leave": {
"title": "Leave team", "title": "Leave team",
"text1": "Are you sure you want to leave this team?", "text1": "Are you sure you want to leave this team?",
"text2": "You will lose access to all projects and namespaces this team has access to. If you change your mind you'll need a team admin to add you again.", "text2": "You will lose access to all projects this team has access to. If you change your mind you'll need a team admin to add you again.",
"success": "You have successfully left the team." "success": "You have successfully left the team."
} }
}, },
@ -897,7 +831,10 @@
"color": "Change the color of this task", "color": "Change the color of this task",
"move": "Move this task to another project", "move": "Move this task to another project",
"reminder": "Manage reminders of this task", "reminder": "Manage reminders of this task",
"description": "Toggle editing of the task description" "description": "Toggle editing of the task description",
"delete": "Delete this task",
"priority": "Change the priority of this task",
"favorite": "Mark this task as favorite / unfavorite"
}, },
"project": { "project": {
"title": "Project Views", "title": "Project Views",
@ -910,9 +847,9 @@
"title": "Navigation", "title": "Navigation",
"overview": "Navigate to overview", "overview": "Navigate to overview",
"upcoming": "Navigate to upcoming tasks", "upcoming": "Navigate to upcoming tasks",
"namespaces": "Navigate to namespaces & projects",
"labels": "Navigate to labels", "labels": "Navigate to labels",
"teams": "Navigate to teams" "teams": "Navigate to teams",
"projects": "Navigate to projects"
} }
}, },
"update": { "update": {
@ -927,7 +864,8 @@
"unarchive": "Un-Archive", "unarchive": "Un-Archive",
"setBackground": "Set background", "setBackground": "Set background",
"share": "Share", "share": "Share",
"newProject": "New project" "newProject": "New project",
"createProject": "Create project"
}, },
"apiConfig": { "apiConfig": {
"url": "Vikunja URL", "url": "Vikunja URL",
@ -946,7 +884,7 @@
"notification": { "notification": {
"title": "Notifications", "title": "Notifications",
"none": "You don't have any notifications. Have a nice day!", "none": "You don't have any notifications. Have a nice day!",
"explainer": "Notifications will appear here when actions on namespaces, projects or tasks you subscribed to happen." "explainer": "Notifications will appear here when actions projects or tasks you subscribed to happen."
}, },
"quickActions": { "quickActions": {
"commands": "Commands", "commands": "Commands",
@ -957,14 +895,12 @@
"teams": "Teams", "teams": "Teams",
"newProject": "Enter the title of the new project…", "newProject": "Enter the title of the new project…",
"newTask": "Enter the title of the new task…", "newTask": "Enter the title of the new task…",
"newNamespace": "Enter the title of the new namespace…",
"newTeam": "Enter the name of the new team…", "newTeam": "Enter the name of the new team…",
"createTask": "Create a task in the current project ({title})", "createTask": "Create a task in the current project ({title})",
"createProject": "Create a project in the current namespace ({title})", "createProject": "Create a project",
"cmds": { "cmds": {
"newTask": "New task", "newTask": "New task",
"newProject": "New project", "newProject": "New project",
"newNamespace": "New namespace",
"newTeam": "New team" "newTeam": "New team"
} }
}, },
@ -1020,16 +956,9 @@
"4017": "Invalid task filter comparator.", "4017": "Invalid task filter comparator.",
"4018": "Invalid task filter concatenator.", "4018": "Invalid task filter concatenator.",
"4019": "Invalid task filter value.", "4019": "Invalid task filter value.",
"5001": "The namespace does not exist.",
"5003": "You do not have access to the specified namespace.",
"5006": "The namespace name cannot be empty.",
"5009": "You need to have namespace read access to perform that action.",
"5010": "This team does not have access to that namespace.",
"5011": "This user has already access to that namespace.",
"5012": "The namespace is archived and can therefore only be accessed read only.",
"6001": "The team name cannot be empty.", "6001": "The team name cannot be empty.",
"6002": "The team does not exist.", "6002": "The team does not exist.",
"6004": "The team already has access to that namespace or project.", "6004": "The team already has access to that project.",
"6005": "The user is already a member of that team.", "6005": "The user is already a member of that team.",
"6006": "Cannot delete the last team member.", "6006": "Cannot delete the last team member.",
"6007": "The team does not have access to the project to perform that action.", "6007": "The team does not have access to the project to perform that action.",
@ -1056,4 +985,4 @@
"frontendVersion": "Frontend Version: {version}", "frontendVersion": "Frontend Version: {version}",
"apiVersion": "API Version: {version}" "apiVersion": "API Version: {version}"
} }
} }

View File

@ -6,9 +6,7 @@
"welcomeEvening": "¡Buenas Tardes {username}!", "welcomeEvening": "¡Buenas Tardes {username}!",
"lastViewed": "Visto por última vez", "lastViewed": "Visto por última vez",
"project": { "project": {
"newText": "You can create a new project for your new tasks:", "importText": "Import your projects and tasks from other services into Vikunja:",
"new": "New project",
"importText": "Or import your projects and tasks from other services into Vikunja:",
"import": "Import your data into Vikunja" "import": "Import your data into Vikunja"
} }
}, },
@ -143,7 +141,7 @@
}, },
"deletion": { "deletion": {
"title": "Eliminar tu Cuenta de Vikunja", "title": "Eliminar tu Cuenta de Vikunja",
"text1": "The deletion of your account is permanent and cannot be undone. We will delete all your namespaces, projects, tasks and everything associated with it.", "text1": "The deletion of your account is permanent and cannot be undone. We will delete all your projects, tasks and everything associated with it.",
"text2": "Para continuar, por favor, introduce tu contraseña. Recibirás un correo electrónico con más instrucciones.", "text2": "Para continuar, por favor, introduce tu contraseña. Recibirás un correo electrónico con más instrucciones.",
"confirm": "Eliminar mi cuenta", "confirm": "Eliminar mi cuenta",
"requestSuccess": "La solicitud ha sido exitosa. Recibirás un correo electrónico con más instrucciones.", "requestSuccess": "La solicitud ha sido exitosa. Recibirás un correo electrónico con más instrucciones.",
@ -157,7 +155,7 @@
}, },
"export": { "export": {
"title": "Exportar tus datos de Vikunja", "title": "Exportar tus datos de Vikunja",
"description": "You can request a copy of all your Vikunja data. This include Namespaces, Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.", "description": "You can request a copy of all your Vikunja data. This includes Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
"descriptionPasswordRequired": "Por favor, introduce tu contraseña para continuar:", "descriptionPasswordRequired": "Por favor, introduce tu contraseña para continuar:",
"request": "Solicitar una copia de mis datos de Vikunja", "request": "Solicitar una copia de mis datos de Vikunja",
"success": "Tu petición de datos de Vikunja ha sido procesada correctamente. Te enviaremos un correo una vez esté lista para descargar.", "success": "Tu petición de datos de Vikunja ha sido procesada correctamente. Te enviaremos un correo una vez esté lista para descargar.",
@ -165,14 +163,18 @@
} }
}, },
"project": { "project": {
"archived": "This project is archived. It is not possible to create new or edit tasks for it.", "archivedMessage": "This project is archived. It is not possible to create new or edit tasks for it.",
"archived": "Archived",
"showArchived": "Show Archived",
"title": "Project Title", "title": "Project Title",
"color": "Color", "color": "Color",
"projects": "Projects", "projects": "Projects",
"parent": "Parent Project",
"search": "Type to search for a project…", "search": "Type to search for a project…",
"searchSelect": "Click or press enter to select this project", "searchSelect": "Click or press enter to select this project",
"shared": "Shared Projects", "shared": "Shared Projects",
"noDescriptionAvailable": "No project description is available.", "noDescriptionAvailable": "No project description is available.",
"inboxTitle": "Inbox",
"create": { "create": {
"header": "New project", "header": "New project",
"titlePlaceholder": "The project's title goes here…", "titlePlaceholder": "The project's title goes here…",
@ -210,7 +212,7 @@
"duplicate": { "duplicate": {
"title": "Duplicate this project", "title": "Duplicate this project",
"label": "Duplicate", "label": "Duplicate",
"text": "Select a namespace which should hold the duplicated project:", "text": "Select a parent project which should hold the duplicated project:",
"success": "The project was successfully duplicated." "success": "The project was successfully duplicated."
}, },
"edit": { "edit": {
@ -321,67 +323,6 @@
} }
} }
}, },
"namespace": {
"title": "Namespaces & Projects",
"namespace": "Proyecto",
"showArchived": "Mostrar Archivados",
"noneAvailable": "No tienes ningún proyecto en este momento.",
"unarchive": "Desarchivar",
"archived": "Archivado",
"noProjects": "This namespace does not contain any projects.",
"createProject": "Create a new project in this namespace.",
"namespaces": "Proyectos",
"search": "Escribe para buscar un proyecto…",
"create": {
"title": "Nuevo proyecto",
"titleRequired": "Por favor, especifica un título.",
"explanation": "A namespace is a collection of projects you can share and use to organize your projects with. In fact, every project belongs to a namespace.",
"tooltip": "¿Qué es un proyecto?",
"success": "El proyecto se ha creado correctamente."
},
"archive": {
"titleArchive": "Archivar \"{namespace}\"",
"titleUnarchive": "Desarchivar \"{namespace}\"",
"archiveText": "You won't be able to edit this namespace or create new projects until you un-archive it. This will also archive all projects in this namespace.",
"unarchiveText": "You will be able to create new projects or edit it.",
"success": "El proyecto fue archivado con éxito.",
"unarchiveSuccess": "El proyecto se ha desarchivado con éxito.",
"description": "If a namespace is archived, you cannot create new projects or edit it."
},
"delete": {
"title": "Eliminar \"{namespace}\"",
"text1": "¿Estás seguro de que deseas eliminar este proyecto y todo su contenido?",
"text2": "This includes all projects and tasks and CANNOT BE UNDONE!",
"success": "El proyecto se ha eliminado con éxito."
},
"edit": {
"title": "Editar \"{namespace}\"",
"success": "El proyecto se actualizó con éxito."
},
"share": {
"title": "Compartir \"{namespace}\""
},
"attributes": {
"title": "Título del proyecto",
"titlePlaceholder": "El título del proyecto va aquí…",
"description": "Descripción",
"descriptionPlaceholder": "La descripción del proyecto va aquí…",
"color": "Color",
"archived": "Está archivado",
"isArchived": "Este proyecto está archivado"
},
"pseudo": {
"sharedProjects": {
"title": "Shared Projects"
},
"favorites": {
"title": "Favoritos"
},
"savedFilters": {
"title": "Filtros"
}
}
},
"filters": { "filters": {
"title": "Filtros", "title": "Filtros",
"clear": "Limpiar Filtros", "clear": "Limpiar Filtros",
@ -403,7 +344,7 @@
}, },
"create": { "create": {
"title": "New Saved Filter", "title": "New Saved Filter",
"description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed. Once created, it will appear in a special namespace.", "description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed.",
"action": "Create new saved filter", "action": "Create new saved filter",
"titleRequired": "Please provide a title for the filter." "titleRequired": "Please provide a title for the filter."
}, },
@ -674,19 +615,13 @@
"updated": "Actualizado" "updated": "Actualizado"
}, },
"subscription": { "subscription": {
"subscribedProjectThroughParentNamespace": "You can't unsubscribe here because you are subscribed to this project through its namespace.",
"subscribedTaskThroughParentNamespace": "No puede cancelar la suscripción aquí porque está suscrito a esta tarea a través de su proyecto.",
"subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.", "subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.",
"subscribedNamespace": "Actualmente está suscrito a este proyecto y recibirás notificaciones de cambios.",
"notSubscribedNamespace": "No está suscrito a este proyecto y no recibirá notificaciones de cambios.",
"subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.", "subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.",
"notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.", "notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.",
"subscribedTask": "Actualmente estás suscrito a esta tarea y recibirás notificaciones de cambios.", "subscribedTask": "Actualmente estás suscrito a esta tarea y recibirás notificaciones de cambios.",
"notSubscribedTask": "No estás suscrito a esta tarea y no recibirás notificaciones de cambios.", "notSubscribedTask": "No estás suscrito a esta tarea y no recibirás notificaciones de cambios.",
"subscribe": "Suscribirse", "subscribe": "Suscribirse",
"unsubscribe": "Desuscribirse", "unsubscribe": "Desuscribirse",
"subscribeSuccessNamespace": "Ahora está suscrito a este proyecto",
"unsubscribeSuccessNamespace": "Ya no está suscrito a este proyecto",
"subscribeSuccessProject": "You are now subscribed to this project", "subscribeSuccessProject": "You are now subscribed to this project",
"unsubscribeSuccessProject": "You are now unsubscribed to this project", "unsubscribeSuccessProject": "You are now unsubscribed to this project",
"subscribeSuccessTask": "You are now subscribed to this task", "subscribeSuccessTask": "You are now subscribed to this task",
@ -763,7 +698,6 @@
"searchPlaceholder": "Escriba para buscar una nueva tarea a añadir como relacionada…", "searchPlaceholder": "Escriba para buscar una nueva tarea a añadir como relacionada…",
"createPlaceholder": "Añadir esto como nueva tarea relacionada", "createPlaceholder": "Añadir esto como nueva tarea relacionada",
"differentProject": "This task belongs to a different project.", "differentProject": "This task belongs to a different project.",
"differentNamespace": "Esta tarea pertenece a un proyecto diferente.",
"noneYet": "Aún no hay tareas relacionadas.", "noneYet": "Aún no hay tareas relacionadas.",
"delete": "Eliminar Relación de Tarea", "delete": "Eliminar Relación de Tarea",
"deleteText1": "¿Está seguro que desea eliminar esta relación de la tarea?", "deleteText1": "¿Está seguro que desea eliminar esta relación de la tarea?",
@ -848,19 +782,19 @@
"delete": { "delete": {
"header": "Delete the team", "header": "Delete the team",
"text1": "Are you sure you want to delete this team and all of its members?", "text1": "Are you sure you want to delete this team and all of its members?",
"text2": "All team members will lose access to projects and namespaces shared with this team. This CANNOT BE UNDONE!", "text2": "All team members will lose access to projects shared with this team. This CANNOT BE UNDONE!",
"success": "El equipo fue eliminado con éxito." "success": "El equipo fue eliminado con éxito."
}, },
"deleteUser": { "deleteUser": {
"header": "Remove a user from the team", "header": "Remove a user from the team",
"text1": "Are you sure you want to remove this user from the team?", "text1": "Are you sure you want to remove this user from the team?",
"text2": "They will lose access to all projects and namespaces this team has access to. This CANNOT BE UNDONE!", "text2": "They will lose access to all projects this team has access to. This CANNOT BE UNDONE!",
"success": "El usuario fue quitado del equipo con éxito." "success": "El usuario fue quitado del equipo con éxito."
}, },
"leave": { "leave": {
"title": "Leave team", "title": "Leave team",
"text1": "Are you sure you want to leave this team?", "text1": "Are you sure you want to leave this team?",
"text2": "You will lose access to all projects and namespaces this team has access to. If you change your mind you'll need a team admin to add you again.", "text2": "You will lose access to all projects this team has access to. If you change your mind you'll need a team admin to add you again.",
"success": "Has abandonado el equipo con éxito." "success": "Has abandonado el equipo con éxito."
} }
}, },
@ -894,7 +828,10 @@
"color": "Cambia el color de esta tarea", "color": "Cambia el color de esta tarea",
"move": "Move this task to another project", "move": "Move this task to another project",
"reminder": "Administrar recordatorios de esta tarea", "reminder": "Administrar recordatorios de esta tarea",
"description": "Editar la descripción de la tarea" "description": "Editar la descripción de la tarea",
"delete": "Delete this task",
"priority": "Change the priority of this task",
"favorite": "Mark this task as favorite / unfavorite"
}, },
"project": { "project": {
"title": "Project Views", "title": "Project Views",
@ -907,9 +844,9 @@
"title": "Secciones", "title": "Secciones",
"overview": "Ir a resumen", "overview": "Ir a resumen",
"upcoming": "Ir a tareas próximas", "upcoming": "Ir a tareas próximas",
"namespaces": "Navigate to namespaces & projects",
"labels": "Ir a etiquetas", "labels": "Ir a etiquetas",
"teams": "Ir a equipos" "teams": "Ir a equipos",
"projects": "Navigate to projects"
} }
}, },
"update": { "update": {
@ -924,7 +861,8 @@
"unarchive": "Desarchivar", "unarchive": "Desarchivar",
"setBackground": "Establecer fondo", "setBackground": "Establecer fondo",
"share": "Compartir", "share": "Compartir",
"newProject": "New project" "newProject": "New project",
"createProject": "Create project"
}, },
"apiConfig": { "apiConfig": {
"url": "URL de Vikunja", "url": "URL de Vikunja",
@ -943,7 +881,7 @@
"notification": { "notification": {
"title": "Notificaciones", "title": "Notificaciones",
"none": "No tienes notificaciones. ¡Que tengas un buen día!", "none": "No tienes notificaciones. ¡Que tengas un buen día!",
"explainer": "Notifications will appear here when actions on namespaces, projects or tasks you subscribed to happen." "explainer": "Notifications will appear here when actions projects or tasks you subscribed to happen."
}, },
"quickActions": { "quickActions": {
"commands": "Commands", "commands": "Commands",
@ -954,14 +892,12 @@
"teams": "Teams", "teams": "Teams",
"newProject": "Enter the title of the new project…", "newProject": "Enter the title of the new project…",
"newTask": "Enter the title of the new task…", "newTask": "Enter the title of the new task…",
"newNamespace": "Enter the title of the new namespace…",
"newTeam": "Enter the name of the new team…", "newTeam": "Enter the name of the new team…",
"createTask": "Create a task in the current project ({title})", "createTask": "Create a task in the current project ({title})",
"createProject": "Create a project in the current namespace ({title})", "createProject": "Create a project",
"cmds": { "cmds": {
"newTask": "New task", "newTask": "New task",
"newProject": "New project", "newProject": "New project",
"newNamespace": "New namespace",
"newTeam": "New team" "newTeam": "New team"
} }
}, },
@ -1017,16 +953,9 @@
"4017": "Comparador de filtro de tarea inválido.", "4017": "Comparador de filtro de tarea inválido.",
"4018": "Concatenador de filtro de tarea inválido.", "4018": "Concatenador de filtro de tarea inválido.",
"4019": "Valor de filtro de tarea inválido.", "4019": "Valor de filtro de tarea inválido.",
"5001": "El proyecto no existe.",
"5003": "No tiene acceso al proyecto especificado.",
"5006": "El nombre del proyecto no puede estar vacío.",
"5009": "Necesita tener acceso de lectura al proyecto para realizar esa acción.",
"5010": "Este equipo no tiene acceso a ese proyecto.",
"5011": "Este usuario ya tiene acceso a ese proyecto.",
"5012": "El proyecto está archivado y por lo tanto solo podrá acceder en modo solo lectura.",
"6001": "El nombre del equipo no puede estar vacío.", "6001": "El nombre del equipo no puede estar vacío.",
"6002": "Este equipo no existe.", "6002": "Este equipo no existe.",
"6004": "The team already has access to that namespace or project.", "6004": "The team already has access to that project.",
"6005": "El usuario ya es miembro de ese equipo.", "6005": "El usuario ya es miembro de ese equipo.",
"6006": "No se puede quitar al último miembro del equipo.", "6006": "No se puede quitar al último miembro del equipo.",
"6007": "The team does not have access to the project to perform that action.", "6007": "The team does not have access to the project to perform that action.",
@ -1053,4 +982,4 @@
"frontendVersion": "Frontend Version: {version}", "frontendVersion": "Frontend Version: {version}",
"apiVersion": "Versión de la API: {version}" "apiVersion": "Versión de la API: {version}"
} }
} }

View File

@ -6,9 +6,7 @@
"welcomeEvening": "Good Evening {username}!", "welcomeEvening": "Good Evening {username}!",
"lastViewed": "Dernière consultation", "lastViewed": "Dernière consultation",
"project": { "project": {
"newText": "You can create a new project for your new tasks:", "importText": "Import your projects and tasks from other services into Vikunja:",
"new": "New project",
"importText": "Or import your projects and tasks from other services into Vikunja:",
"import": "Import your data into Vikunja" "import": "Import your data into Vikunja"
} }
}, },
@ -143,7 +141,7 @@
}, },
"deletion": { "deletion": {
"title": "Supprimer ton compte Vikunja", "title": "Supprimer ton compte Vikunja",
"text1": "The deletion of your account is permanent and cannot be undone. We will delete all your namespaces, projects, tasks and everything associated with it.", "text1": "The deletion of your account is permanent and cannot be undone. We will delete all your projects, tasks and everything associated with it.",
"text2": "Pour continuer, entre ton mot de passe. Tu recevras un courriel contenant les instructions suivantes.", "text2": "Pour continuer, entre ton mot de passe. Tu recevras un courriel contenant les instructions suivantes.",
"confirm": "Supprimer mon compte", "confirm": "Supprimer mon compte",
"requestSuccess": "La demande a réussi. Tu recevras un courriel avec des instructions supplémentaires.", "requestSuccess": "La demande a réussi. Tu recevras un courriel avec des instructions supplémentaires.",
@ -157,7 +155,7 @@
}, },
"export": { "export": {
"title": "Exporter tes données Vikunja", "title": "Exporter tes données Vikunja",
"description": "You can request a copy of all your Vikunja data. This include Namespaces, Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.", "description": "You can request a copy of all your Vikunja data. This includes Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
"descriptionPasswordRequired": "Entre ton mot de passe pour continuer :", "descriptionPasswordRequired": "Entre ton mot de passe pour continuer :",
"request": "Demander une copie de mes données Vikunja", "request": "Demander une copie de mes données Vikunja",
"success": "Tu as bien demandé tes données Vikunja ! Nous t'enverrons un courriel dès qu'elles seront prêtes à être téléchargées.", "success": "Tu as bien demandé tes données Vikunja ! Nous t'enverrons un courriel dès qu'elles seront prêtes à être téléchargées.",
@ -165,14 +163,18 @@
} }
}, },
"project": { "project": {
"archived": "This project is archived. It is not possible to create new or edit tasks for it.", "archivedMessage": "This project is archived. It is not possible to create new or edit tasks for it.",
"archived": "Archived",
"showArchived": "Show Archived",
"title": "Project Title", "title": "Project Title",
"color": "Color", "color": "Color",
"projects": "Projects", "projects": "Projects",
"parent": "Parent Project",
"search": "Type to search for a project…", "search": "Type to search for a project…",
"searchSelect": "Click or press enter to select this project", "searchSelect": "Click or press enter to select this project",
"shared": "Shared Projects", "shared": "Shared Projects",
"noDescriptionAvailable": "No project description is available.", "noDescriptionAvailable": "No project description is available.",
"inboxTitle": "Inbox",
"create": { "create": {
"header": "New project", "header": "New project",
"titlePlaceholder": "The project's title goes here…", "titlePlaceholder": "The project's title goes here…",
@ -210,7 +212,7 @@
"duplicate": { "duplicate": {
"title": "Duplicate this project", "title": "Duplicate this project",
"label": "Duplicate", "label": "Duplicate",
"text": "Select a namespace which should hold the duplicated project:", "text": "Select a parent project which should hold the duplicated project:",
"success": "The project was successfully duplicated." "success": "The project was successfully duplicated."
}, },
"edit": { "edit": {
@ -321,67 +323,6 @@
} }
} }
}, },
"namespace": {
"title": "Namespaces & Projects",
"namespace": "Espace de noms",
"showArchived": "Montrer les archivés",
"noneAvailable": "Tu nas pas despace de noms pour le moment.",
"unarchive": "Désarchiver",
"archived": "Archivé",
"noProjects": "This namespace does not contain any projects.",
"createProject": "Create a new project in this namespace.",
"namespaces": "Espaces de noms",
"search": "Écris pour rechercher un espace de noms…",
"create": {
"title": "Nouvel espace de noms",
"titleRequired": "Indique un nom.",
"explanation": "A namespace is a collection of projects you can share and use to organize your projects with. In fact, every project belongs to a namespace.",
"tooltip": "Quest-ce quun espace de noms ?",
"success": "Espace de noms créé."
},
"archive": {
"titleArchive": "Archiver « {namespace} »",
"titleUnarchive": "Désarchiver « {namespace} »",
"archiveText": "You won't be able to edit this namespace or create new projects until you un-archive it. This will also archive all projects in this namespace.",
"unarchiveText": "You will be able to create new projects or edit it.",
"success": "Espace de noms archivé.",
"unarchiveSuccess": "Espace de noms archivé.",
"description": "If a namespace is archived, you cannot create new projects or edit it."
},
"delete": {
"title": "Supprimer « {namespace} »",
"text1": "Supprimer cet espace de noms et tout son contenu ?",
"text2": "This includes all projects and tasks and CANNOT BE UNDONE!",
"success": "Espace de noms supprimé."
},
"edit": {
"title": "Modifier « {namespace} »",
"success": "Espace de noms mis à jour."
},
"share": {
"title": "Partager « {namespace} »"
},
"attributes": {
"title": "Nom de lespace de noms",
"titlePlaceholder": "Entre le nom de lespace de noms…",
"description": "Description",
"descriptionPlaceholder": "Entre la description de lespace de noms…",
"color": "Couleur",
"archived": "Est archivé",
"isArchived": "Cet espace de noms est archivé"
},
"pseudo": {
"sharedProjects": {
"title": "Shared Projects"
},
"favorites": {
"title": "Favoris"
},
"savedFilters": {
"title": "Filtres"
}
}
},
"filters": { "filters": {
"title": "Filtres", "title": "Filtres",
"clear": "Effacer les filtres", "clear": "Effacer les filtres",
@ -403,7 +344,7 @@
}, },
"create": { "create": {
"title": "Nouveau filtre enregistré", "title": "Nouveau filtre enregistré",
"description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed. Once created, it will appear in a special namespace.", "description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed.",
"action": "Créer un nouveau filtre enregistré", "action": "Créer un nouveau filtre enregistré",
"titleRequired": "Please provide a title for the filter." "titleRequired": "Please provide a title for the filter."
}, },
@ -674,19 +615,13 @@
"updated": "Mis à jour" "updated": "Mis à jour"
}, },
"subscription": { "subscription": {
"subscribedProjectThroughParentNamespace": "You can't unsubscribe here because you are subscribed to this project through its namespace.",
"subscribedTaskThroughParentNamespace": "You can't unsubscribe here because you are subscribed to this task through its namespace.",
"subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.", "subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.",
"subscribedNamespace": "You are currently subscribed to this namespace and will receive notifications for changes.",
"notSubscribedNamespace": "You are not subscribed to this namespace and won't receive notifications for changes.",
"subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.", "subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.",
"notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.", "notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.",
"subscribedTask": "You are currently subscribed to this task and will receive notifications for changes.", "subscribedTask": "You are currently subscribed to this task and will receive notifications for changes.",
"notSubscribedTask": "You are not subscribed to this task and won't receive notifications for changes.", "notSubscribedTask": "You are not subscribed to this task and won't receive notifications for changes.",
"subscribe": "Sabonner", "subscribe": "Sabonner",
"unsubscribe": "Se désabonner", "unsubscribe": "Se désabonner",
"subscribeSuccessNamespace": "You are now subscribed to this namespace",
"unsubscribeSuccessNamespace": "You are now unsubscribed to this namespace",
"subscribeSuccessProject": "You are now subscribed to this project", "subscribeSuccessProject": "You are now subscribed to this project",
"unsubscribeSuccessProject": "You are now unsubscribed to this project", "unsubscribeSuccessProject": "You are now unsubscribed to this project",
"subscribeSuccessTask": "You are now subscribed to this task", "subscribeSuccessTask": "You are now subscribed to this task",
@ -763,7 +698,6 @@
"searchPlaceholder": "Écris la recherche dune nouvelle tâche à ajouter comme connexe…", "searchPlaceholder": "Écris la recherche dune nouvelle tâche à ajouter comme connexe…",
"createPlaceholder": "Ajouter cette tâche comme nouvelle tâche connexe", "createPlaceholder": "Ajouter cette tâche comme nouvelle tâche connexe",
"differentProject": "This task belongs to a different project.", "differentProject": "This task belongs to a different project.",
"differentNamespace": "Cette tâche fait partie d'un espace de noms différent.",
"noneYet": "Pas encore de relations de tâches.", "noneYet": "Pas encore de relations de tâches.",
"delete": "Supprimer la relation de tâche", "delete": "Supprimer la relation de tâche",
"deleteText1": "Supprimer cette relation de tâche ?", "deleteText1": "Supprimer cette relation de tâche ?",
@ -848,19 +782,19 @@
"delete": { "delete": {
"header": "Supprimer léquipe", "header": "Supprimer léquipe",
"text1": "Supprimer cette équipe et tous ses membres ?", "text1": "Supprimer cette équipe et tous ses membres ?",
"text2": "All team members will lose access to projects and namespaces shared with this team. This CANNOT BE UNDONE!", "text2": "All team members will lose access to projects shared with this team. This CANNOT BE UNDONE!",
"success": "Équipe supprimée." "success": "Équipe supprimée."
}, },
"deleteUser": { "deleteUser": {
"header": "Retirer un·e utilisateur·rice de léquipe", "header": "Retirer un·e utilisateur·rice de léquipe",
"text1": "Retirer cette personne de léquipe ?", "text1": "Retirer cette personne de léquipe ?",
"text2": "They will lose access to all projects and namespaces this team has access to. This CANNOT BE UNDONE!", "text2": "They will lose access to all projects this team has access to. This CANNOT BE UNDONE!",
"success": "Utilisateur·rice retiré·e de léquipe." "success": "Utilisateur·rice retiré·e de léquipe."
}, },
"leave": { "leave": {
"title": "Leave team", "title": "Leave team",
"text1": "Are you sure you want to leave this team?", "text1": "Are you sure you want to leave this team?",
"text2": "You will lose access to all projects and namespaces this team has access to. If you change your mind you'll need a team admin to add you again.", "text2": "You will lose access to all projects this team has access to. If you change your mind you'll need a team admin to add you again.",
"success": "You have successfully left the team." "success": "You have successfully left the team."
} }
}, },
@ -894,7 +828,10 @@
"color": "Changer la couleur de cette tâche", "color": "Changer la couleur de cette tâche",
"move": "Move this task to another project", "move": "Move this task to another project",
"reminder": "Manage reminders of this task", "reminder": "Manage reminders of this task",
"description": "Toggle editing of the task description" "description": "Toggle editing of the task description",
"delete": "Delete this task",
"priority": "Change the priority of this task",
"favorite": "Mark this task as favorite / unfavorite"
}, },
"project": { "project": {
"title": "Project Views", "title": "Project Views",
@ -907,9 +844,9 @@
"title": "Navigation", "title": "Navigation",
"overview": "Navigate to overview", "overview": "Navigate to overview",
"upcoming": "Navigate to upcoming tasks", "upcoming": "Navigate to upcoming tasks",
"namespaces": "Navigate to namespaces & projects",
"labels": "Accéder aux étiquettes", "labels": "Accéder aux étiquettes",
"teams": "Accéder aux équipes" "teams": "Accéder aux équipes",
"projects": "Navigate to projects"
} }
}, },
"update": { "update": {
@ -924,7 +861,8 @@
"unarchive": "Désarchiver", "unarchive": "Désarchiver",
"setBackground": "Définir larrière-plan", "setBackground": "Définir larrière-plan",
"share": "Partager", "share": "Partager",
"newProject": "New project" "newProject": "New project",
"createProject": "Create project"
}, },
"apiConfig": { "apiConfig": {
"url": "URL Vikunja", "url": "URL Vikunja",
@ -943,7 +881,7 @@
"notification": { "notification": {
"title": "Notifications", "title": "Notifications",
"none": "Tu nas pas de notifications. Passe une bonne journée !", "none": "Tu nas pas de notifications. Passe une bonne journée !",
"explainer": "Notifications will appear here when actions on namespaces, projects or tasks you subscribed to happen." "explainer": "Notifications will appear here when actions projects or tasks you subscribed to happen."
}, },
"quickActions": { "quickActions": {
"commands": "Commandes", "commands": "Commandes",
@ -954,14 +892,12 @@
"teams": "Équipes", "teams": "Équipes",
"newProject": "Enter the title of the new project…", "newProject": "Enter the title of the new project…",
"newTask": "Entre le nom de la tâche…", "newTask": "Entre le nom de la tâche…",
"newNamespace": "Entre le nom de lespace de noms…",
"newTeam": "Entre le nom de la nouvelle équipe…", "newTeam": "Entre le nom de la nouvelle équipe…",
"createTask": "Create a task in the current project ({title})", "createTask": "Create a task in the current project ({title})",
"createProject": "Create a project in the current namespace ({title})", "createProject": "Create a project",
"cmds": { "cmds": {
"newTask": "Nouvelle tâche", "newTask": "Nouvelle tâche",
"newProject": "New project", "newProject": "New project",
"newNamespace": "Nouvel espace de noms",
"newTeam": "Nouvelle équipe" "newTeam": "Nouvelle équipe"
} }
}, },
@ -1017,16 +953,9 @@
"4017": "Comparateur de filtre de tâche invalide.", "4017": "Comparateur de filtre de tâche invalide.",
"4018": "Concaténateur de filtre de tâche invalide.", "4018": "Concaténateur de filtre de tâche invalide.",
"4019": "Valeur de filtre de tâche invalide.", "4019": "Valeur de filtre de tâche invalide.",
"5001": "Lespace de noms nexiste pas.",
"5003": "Tu nas pas accès à lespace de noms indiqué.",
"5006": "Le nom de lespace de noms ne peut pas être vide.",
"5009": "Accès en lecture à lespace de noms nécessaire pour effectuer cette action.",
"5010": "Cette équipe na pas accès à cet espace de noms.",
"5011": "Cet·e utilisateur·rice a déjà accès à cet espace de noms.",
"5012": "Lespace de noms est archivé et ne peut donc être consulté quen lecture seule.",
"6001": "Le nom de l'équipe ne peut pas être vide.", "6001": "Le nom de l'équipe ne peut pas être vide.",
"6002": "Léquipe nexiste pas.", "6002": "Léquipe nexiste pas.",
"6004": "The team already has access to that namespace or project.", "6004": "The team already has access to that project.",
"6005": "Lutilisateur·rice est déjà membre de cette équipe.", "6005": "Lutilisateur·rice est déjà membre de cette équipe.",
"6006": "Impossible de supprimer le dernier membre de léquipe.", "6006": "Impossible de supprimer le dernier membre de léquipe.",
"6007": "The team does not have access to the project to perform that action.", "6007": "The team does not have access to the project to perform that action.",
@ -1053,4 +982,4 @@
"frontendVersion": "Version : {version}", "frontendVersion": "Version : {version}",
"apiVersion": "Version de lAPI : {version}" "apiVersion": "Version de lAPI : {version}"
} }
} }

View File

@ -6,10 +6,8 @@
"welcomeEvening": "Buonasera {username}!", "welcomeEvening": "Buonasera {username}!",
"lastViewed": "Ultima visualizzazione", "lastViewed": "Ultima visualizzazione",
"project": { "project": {
"newText": "You can create a new project for your new tasks:", "importText": "Import your projects and tasks from other services into Vikunja:",
"new": "New project", "import": "Importa i tuoi dati in Vikunja"
"importText": "Or import your projects and tasks from other services into Vikunja:",
"import": "Import your data into Vikunja"
} }
}, },
"404": { "404": {
@ -85,7 +83,7 @@
"weekStartSunday": "Domenica", "weekStartSunday": "Domenica",
"weekStartMonday": "Lunedì", "weekStartMonday": "Lunedì",
"language": "Lingua", "language": "Lingua",
"defaultProject": "Default Project", "defaultProject": "Progetto Predefinito",
"timezone": "Fuso Orario", "timezone": "Fuso Orario",
"overdueTasksRemindersTime": "Orario email attività in scadute" "overdueTasksRemindersTime": "Orario email attività in scadute"
}, },
@ -143,7 +141,7 @@
}, },
"deletion": { "deletion": {
"title": "Elimina il tuo Account Vikunja", "title": "Elimina il tuo Account Vikunja",
"text1": "The deletion of your account is permanent and cannot be undone. We will delete all your namespaces, projects, tasks and everything associated with it.", "text1": "The deletion of your account is permanent and cannot be undone. We will delete all your projects, tasks and everything associated with it.",
"text2": "Per continuare, inserisci la tua password. Riceverai un'e-mail con ulteriori istruzioni.", "text2": "Per continuare, inserisci la tua password. Riceverai un'e-mail con ulteriori istruzioni.",
"confirm": "Elimina il mio profilo", "confirm": "Elimina il mio profilo",
"requestSuccess": "Richiesta riuscita. Riceverai un'e-mail con ulteriori istruzioni.", "requestSuccess": "Richiesta riuscita. Riceverai un'e-mail con ulteriori istruzioni.",
@ -157,7 +155,7 @@
}, },
"export": { "export": {
"title": "Esporta i tuoi dati Vikunja", "title": "Esporta i tuoi dati Vikunja",
"description": "You can request a copy of all your Vikunja data. This include Namespaces, Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.", "description": "You can request a copy of all your Vikunja data. This includes Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
"descriptionPasswordRequired": "Inserisci la tua password per procedere:", "descriptionPasswordRequired": "Inserisci la tua password per procedere:",
"request": "Richiedi una copia dei miei dati Vikunja", "request": "Richiedi una copia dei miei dati Vikunja",
"success": "Hai richiesto con successo i tuoi dati Vikunja! Ti invieremo un'e-mail una volta che saranno pronti da scaricare.", "success": "Hai richiesto con successo i tuoi dati Vikunja! Ti invieremo un'e-mail una volta che saranno pronti da scaricare.",
@ -165,42 +163,46 @@
} }
}, },
"project": { "project": {
"archived": "This project is archived. It is not possible to create new or edit tasks for it.", "archivedMessage": "This project is archived. It is not possible to create new or edit tasks for it.",
"title": "Project Title", "archived": "Archived",
"color": "Color", "showArchived": "Show Archived",
"projects": "Projects", "title": "Titolo Progetto",
"color": "Colore",
"projects": "Progetti",
"parent": "Parent Project",
"search": "Type to search for a project…", "search": "Type to search for a project…",
"searchSelect": "Click or press enter to select this project", "searchSelect": "Click or press enter to select this project",
"shared": "Shared Projects", "shared": "Progetti Condivisi",
"noDescriptionAvailable": "No project description is available.", "noDescriptionAvailable": "No project description is available.",
"inboxTitle": "Inbox",
"create": { "create": {
"header": "New project", "header": "Nuovo progetto",
"titlePlaceholder": "The project's title goes here…", "titlePlaceholder": "Titolo del progetto…",
"addTitleRequired": "Please specify a title.", "addTitleRequired": "Specifica un titolo.",
"createdSuccess": "The project was successfully created.", "createdSuccess": "Progetto creato.",
"addProjectRequired": "Please specify a project or set a default project in the settings." "addProjectRequired": "Please specify a project or set a default project in the settings."
}, },
"archive": { "archive": {
"title": "Archive \"{project}\"", "title": "Archivia \"{project}\"",
"archive": "Archive this project", "archive": "Archivia questo progetto",
"unarchive": "Un-Archive this project", "unarchive": "Estrai questo progetto dall'archivio",
"unarchiveText": "You will be able to create new tasks or edit it.", "unarchiveText": "You will be able to create new tasks or edit it.",
"archiveText": "You won't be able to edit this project or create new tasks until you un-archive it.", "archiveText": "You won't be able to edit this project or create new tasks until you un-archive it.",
"success": "The project was successfully archived." "success": "Progetto archiviato."
}, },
"background": { "background": {
"title": "Set project background", "title": "Imposta lo sfondo del progetto",
"remove": "Remove Background", "remove": "Rimuovi lo sfondo",
"upload": "Choose a background from your pc", "upload": "Scegli uno sfondo dal tuo PC",
"searchPlaceholder": "Search for a background…", "searchPlaceholder": "Cerca uno sfondo…",
"poweredByUnsplash": "Powered by Unsplash", "poweredByUnsplash": "Alimentato da Unsplash",
"loadMore": "Load more photos", "loadMore": "Carica altre foto",
"success": "The background has been set successfully!", "success": "The background has been set successfully!",
"removeSuccess": "The background has been removed successfully!" "removeSuccess": "The background has been removed successfully!"
}, },
"delete": { "delete": {
"title": "Delete \"{project}\"", "title": "Elimina \"{project}\"",
"header": "Delete this project", "header": "Elimina questo progetto",
"text1": "Are you sure you want to delete this project and all of its contents?", "text1": "Are you sure you want to delete this project and all of its contents?",
"text2": "This includes all tasks and CANNOT BE UNDONE!", "text2": "This includes all tasks and CANNOT BE UNDONE!",
"success": "The project was successfully deleted.", "success": "The project was successfully deleted.",
@ -208,27 +210,27 @@
"noTasksToDelete": "This project does not contain any tasks, it should be safe to delete." "noTasksToDelete": "This project does not contain any tasks, it should be safe to delete."
}, },
"duplicate": { "duplicate": {
"title": "Duplicate this project", "title": "Duplica il progetto",
"label": "Duplicate", "label": "Duplica",
"text": "Select a namespace which should hold the duplicated project:", "text": "Select a parent project which should hold the duplicated project:",
"success": "The project was successfully duplicated." "success": "The project was successfully duplicated."
}, },
"edit": { "edit": {
"header": "Edit This Project", "header": "Modifica Questo Progetto",
"title": "Edit \"{project}\"", "title": "Modifica \"{project}\"",
"titlePlaceholder": "The project title goes here…", "titlePlaceholder": "Titolo del progetto…",
"identifierTooltip": "The project identifier can be used to uniquely identify a task across projects. You can set it to empty to disable it.", "identifierTooltip": "The project identifier can be used to uniquely identify a task across projects. You can set it to empty to disable it.",
"identifier": "Project Identifier", "identifier": "Project Identifier",
"identifierPlaceholder": "The project identifier goes here…", "identifierPlaceholder": "The project identifier goes here…",
"description": "Description", "description": "Descrizione",
"descriptionPlaceholder": "The projects description goes here…", "descriptionPlaceholder": "Descrizione del progetto…",
"color": "Color", "color": "Colore",
"success": "The project was successfully updated." "success": "The project was successfully updated."
}, },
"share": { "share": {
"header": "Share this project", "header": "Condividi questo progetto",
"title": "Share \"{project}\"", "title": "Condividi \"{project}\"",
"share": "Share", "share": "Condividi",
"links": { "links": {
"title": "Share Links", "title": "Share Links",
"what": "What is a share link?", "what": "What is a share link?",
@ -321,67 +323,6 @@
} }
} }
}, },
"namespace": {
"title": "Namespaces & Projects",
"namespace": "Namespace",
"showArchived": "Mostra Archiviati",
"noneAvailable": "Non hai alcun namespace in questo momento.",
"unarchive": "De-Archivia",
"archived": "Archiviato",
"noProjects": "This namespace does not contain any projects.",
"createProject": "Create a new project in this namespace.",
"namespaces": "Namespace",
"search": "Digita per cercare un namespace…",
"create": {
"title": "Nuovo namespace",
"titleRequired": "Specifica un titolo.",
"explanation": "A namespace is a collection of projects you can share and use to organize your projects with. In fact, every project belongs to a namespace.",
"tooltip": "Che cos'è un namespace?",
"success": "Namespace creato."
},
"archive": {
"titleArchive": "Archivia \"{namespace}\"",
"titleUnarchive": "Disarchivia \"{namespace}\"",
"archiveText": "You won't be able to edit this namespace or create new projects until you un-archive it. This will also archive all projects in this namespace.",
"unarchiveText": "You will be able to create new projects or edit it.",
"success": "Namespace creato.",
"unarchiveSuccess": "Namespace estratto dall'archivio.",
"description": "If a namespace is archived, you cannot create new projects or edit it."
},
"delete": {
"title": "Elimina \"{namespace}\"",
"text1": "Sei sicuro di voler rimuovere questo namespace e tutto il relativo contenuto?",
"text2": "This includes all projects and tasks and CANNOT BE UNDONE!",
"success": "Namespace eliminato."
},
"edit": {
"title": "Modifica \"{namespace}\"",
"success": "Namespace aggiornato."
},
"share": {
"title": "Condividi \"{namespace}\""
},
"attributes": {
"title": "Titolo del Namespace",
"titlePlaceholder": "Il titolo del namespace va qui…",
"description": "Descrizione",
"descriptionPlaceholder": "La descrizione del namespace va qui…",
"color": "Colore",
"archived": "Archiviato",
"isArchived": "Questo namespace è archiviato"
},
"pseudo": {
"sharedProjects": {
"title": "Shared Projects"
},
"favorites": {
"title": "Preferiti"
},
"savedFilters": {
"title": "Filtri"
}
}
},
"filters": { "filters": {
"title": "Filtri", "title": "Filtri",
"clear": "Pulisci Filtri", "clear": "Pulisci Filtri",
@ -403,7 +344,7 @@
}, },
"create": { "create": {
"title": "Nuovo Filtro Salvato", "title": "Nuovo Filtro Salvato",
"description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed. Once created, it will appear in a special namespace.", "description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed.",
"action": "Crea nuovo filtro salvato", "action": "Crea nuovo filtro salvato",
"titleRequired": "È necessario un titolo per il filtro." "titleRequired": "È necessario un titolo per il filtro."
}, },
@ -674,19 +615,13 @@
"updated": "Aggiornato" "updated": "Aggiornato"
}, },
"subscription": { "subscription": {
"subscribedProjectThroughParentNamespace": "You can't unsubscribe here because you are subscribed to this project through its namespace.",
"subscribedTaskThroughParentNamespace": "Non puoi annullare l'iscrizione perché sei iscritto al namespace di questa attività.",
"subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.", "subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.",
"subscribedNamespace": "Sei iscritto a questo namespace e verrai notificato delle modifiche.",
"notSubscribedNamespace": "Non sei iscritto a questo namespace e non verrai notificato delle modifiche.",
"subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.", "subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.",
"notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.", "notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.",
"subscribedTask": "Sei iscritto a questa attività e verrai notificato delle modifiche.", "subscribedTask": "Sei iscritto a questa attività e verrai notificato delle modifiche.",
"notSubscribedTask": "Non sei iscritto a questa attività e non verrai notificato delle modifiche.", "notSubscribedTask": "Non sei iscritto a questa attività e non verrai notificato delle modifiche.",
"subscribe": "Iscriviti", "subscribe": "Iscriviti",
"unsubscribe": "Disiscriviti", "unsubscribe": "Disiscriviti",
"subscribeSuccessNamespace": "Sei iscritto a questo namespace",
"unsubscribeSuccessNamespace": "Non sei più iscritto a questo namespace",
"subscribeSuccessProject": "You are now subscribed to this project", "subscribeSuccessProject": "You are now subscribed to this project",
"unsubscribeSuccessProject": "You are now unsubscribed to this project", "unsubscribeSuccessProject": "You are now unsubscribed to this project",
"subscribeSuccessTask": "Sei iscritto a questa attività", "subscribeSuccessTask": "Sei iscritto a questa attività",
@ -763,7 +698,6 @@
"searchPlaceholder": "Digita per cercare un'attività da aggiungere come collegata…", "searchPlaceholder": "Digita per cercare un'attività da aggiungere come collegata…",
"createPlaceholder": "Aggiungi come attività collegata", "createPlaceholder": "Aggiungi come attività collegata",
"differentProject": "This task belongs to a different project.", "differentProject": "This task belongs to a different project.",
"differentNamespace": "Questa attività appartiene ad un namespace diverso.",
"noneYet": "Nessuna attività collegata.", "noneYet": "Nessuna attività collegata.",
"delete": "Elimina Collegamento Attività", "delete": "Elimina Collegamento Attività",
"deleteText1": "Confermi di voler eliminare questo collegamento attività?", "deleteText1": "Confermi di voler eliminare questo collegamento attività?",
@ -848,19 +782,19 @@
"delete": { "delete": {
"header": "Elimina il gruppo", "header": "Elimina il gruppo",
"text1": "Sei sicuro di voler eliminare questo gruppo e tutti i suoi membri?", "text1": "Sei sicuro di voler eliminare questo gruppo e tutti i suoi membri?",
"text2": "All team members will lose access to projects and namespaces shared with this team. This CANNOT BE UNDONE!", "text2": "All team members will lose access to projects shared with this team. This CANNOT BE UNDONE!",
"success": "Gruppo eliminato." "success": "Gruppo eliminato."
}, },
"deleteUser": { "deleteUser": {
"header": "Rimuovi un utente dal gruppo", "header": "Rimuovi un utente dal gruppo",
"text1": "Confermi di voler rimuovere questo utente dal gruppo?", "text1": "Confermi di voler rimuovere questo utente dal gruppo?",
"text2": "They will lose access to all projects and namespaces this team has access to. This CANNOT BE UNDONE!", "text2": "They will lose access to all projects this team has access to. This CANNOT BE UNDONE!",
"success": "Utente rimosso dal gruppo." "success": "Utente rimosso dal gruppo."
}, },
"leave": { "leave": {
"title": "Abbandona il gruppo", "title": "Abbandona il gruppo",
"text1": "Sei sicuro di voler abbandonare questo gruppo?", "text1": "Sei sicuro di voler abbandonare questo gruppo?",
"text2": "You will lose access to all projects and namespaces this team has access to. If you change your mind you'll need a team admin to add you again.", "text2": "You will lose access to all projects this team has access to. If you change your mind you'll need a team admin to add you again.",
"success": "Hai abbandonato il gruppo." "success": "Hai abbandonato il gruppo."
} }
}, },
@ -894,7 +828,10 @@
"color": "Cambia il colore di questa attività", "color": "Cambia il colore di questa attività",
"move": "Move this task to another project", "move": "Move this task to another project",
"reminder": "Gestisci i promemoria di questa attività", "reminder": "Gestisci i promemoria di questa attività",
"description": "Attiva/Disattiva modifica della descrizione dell'attività" "description": "Attiva/Disattiva modifica della descrizione dell'attività",
"delete": "Elimina questa attività",
"priority": "Modifica la priorità di questa attività",
"favorite": "Segna questa attività come preferita o non preferita"
}, },
"project": { "project": {
"title": "Project Views", "title": "Project Views",
@ -907,9 +844,9 @@
"title": "Navigazione", "title": "Navigazione",
"overview": "Passa a \"Panoramica\"", "overview": "Passa a \"Panoramica\"",
"upcoming": "Passa a \"Prossimamente\"", "upcoming": "Passa a \"Prossimamente\"",
"namespaces": "Navigate to namespaces & projects",
"labels": "Passa a \"Etichette\"", "labels": "Passa a \"Etichette\"",
"teams": "Passa a \"Gruppi\"" "teams": "Passa a \"Gruppi\"",
"projects": "Navigate to projects"
} }
}, },
"update": { "update": {
@ -924,7 +861,8 @@
"unarchive": "Disarchivia", "unarchive": "Disarchivia",
"setBackground": "Imposta sfondo", "setBackground": "Imposta sfondo",
"share": "Condividi", "share": "Condividi",
"newProject": "New project" "newProject": "New project",
"createProject": "Create project"
}, },
"apiConfig": { "apiConfig": {
"url": "URL Vikunja", "url": "URL Vikunja",
@ -943,7 +881,7 @@
"notification": { "notification": {
"title": "Notifiche", "title": "Notifiche",
"none": "Nessuna notifica. Buona giornata!", "none": "Nessuna notifica. Buona giornata!",
"explainer": "Notifications will appear here when actions on namespaces, projects or tasks you subscribed to happen." "explainer": "Notifications will appear here when actions projects or tasks you subscribed to happen."
}, },
"quickActions": { "quickActions": {
"commands": "Comandi", "commands": "Comandi",
@ -954,14 +892,12 @@
"teams": "Gruppi", "teams": "Gruppi",
"newProject": "Enter the title of the new project…", "newProject": "Enter the title of the new project…",
"newTask": "Inserisci il titolo della nuova attività…", "newTask": "Inserisci il titolo della nuova attività…",
"newNamespace": "Inserisci il titolo del nuovo namespace…",
"newTeam": "Inserisci il nome del nuovo gruppo…", "newTeam": "Inserisci il nome del nuovo gruppo…",
"createTask": "Create a task in the current project ({title})", "createTask": "Create a task in the current project ({title})",
"createProject": "Create a project in the current namespace ({title})", "createProject": "Create a project",
"cmds": { "cmds": {
"newTask": "Nuova attività", "newTask": "Nuova attività",
"newProject": "New project", "newProject": "New project",
"newNamespace": "Nuovo Namespace",
"newTeam": "Nuovo gruppo" "newTeam": "Nuovo gruppo"
} }
}, },
@ -1017,16 +953,9 @@
"4017": "Comparatore di filtri attività non valido.", "4017": "Comparatore di filtri attività non valido.",
"4018": "Concatenatore filtro attività non valido.", "4018": "Concatenatore filtro attività non valido.",
"4019": "Filtro attività non valido.", "4019": "Filtro attività non valido.",
"5001": "Il namespace non esiste.",
"5003": "Non hai accesso a questo namespace.",
"5006": "Il nome del namespace non può essere vuoto.",
"5009": "Devi avere accesso in lettura al namespace per effettuare questa operazione.",
"5010": "Il tuo gruppo non ha accesso a questo namespace.",
"5011": "Questo utente ha già accesso a quel namespace.",
"5012": "Il namespace è archiviato e può quindi essere accessibile solo in sola lettura.",
"6001": "Il nome del gruppo non può essere vuoto.", "6001": "Il nome del gruppo non può essere vuoto.",
"6002": "Gruppo non esistente.", "6002": "Gruppo non esistente.",
"6004": "The team already has access to that namespace or project.", "6004": "The team already has access to that project.",
"6005": "L'utente è già membro di quel gruppo.", "6005": "L'utente è già membro di quel gruppo.",
"6006": "Non è possibile eliminare l'ultimo membro del gruppo.", "6006": "Non è possibile eliminare l'ultimo membro del gruppo.",
"6007": "The team does not have access to the project to perform that action.", "6007": "The team does not have access to the project to perform that action.",
@ -1053,4 +982,4 @@
"frontendVersion": "Versione Frontend: {version}", "frontendVersion": "Versione Frontend: {version}",
"apiVersion": "Versione API: {version}" "apiVersion": "Versione API: {version}"
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -6,9 +6,7 @@
"welcomeEvening": "Good Evening {username}!", "welcomeEvening": "Good Evening {username}!",
"lastViewed": "Laatst bekeken", "lastViewed": "Laatst bekeken",
"project": { "project": {
"newText": "You can create a new project for your new tasks:", "importText": "Import your projects and tasks from other services into Vikunja:",
"new": "New project",
"importText": "Or import your projects and tasks from other services into Vikunja:",
"import": "Import your data into Vikunja" "import": "Import your data into Vikunja"
} }
}, },
@ -143,7 +141,7 @@
}, },
"deletion": { "deletion": {
"title": "Verwijder je Vikunja account", "title": "Verwijder je Vikunja account",
"text1": "The deletion of your account is permanent and cannot be undone. We will delete all your namespaces, projects, tasks and everything associated with it.", "text1": "The deletion of your account is permanent and cannot be undone. We will delete all your projects, tasks and everything associated with it.",
"text2": "Graag je wachtwoord invullen om verder te gaan. Je zult een e-mail ontvangen met verdere instructies.", "text2": "Graag je wachtwoord invullen om verder te gaan. Je zult een e-mail ontvangen met verdere instructies.",
"confirm": "Verwijder mijn account", "confirm": "Verwijder mijn account",
"requestSuccess": "Het verzoek was succesvol. Je ontvangt een e-mail met verdere instructies.", "requestSuccess": "Het verzoek was succesvol. Je ontvangt een e-mail met verdere instructies.",
@ -157,7 +155,7 @@
}, },
"export": { "export": {
"title": "Je Vikunja gegevens exporteren", "title": "Je Vikunja gegevens exporteren",
"description": "You can request a copy of all your Vikunja data. This include Namespaces, Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.", "description": "You can request a copy of all your Vikunja data. This includes Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
"descriptionPasswordRequired": "Voer je wachtwoord in om door te gaan:", "descriptionPasswordRequired": "Voer je wachtwoord in om door te gaan:",
"request": "Een kopie van mijn Vikunja gegevens opvragen", "request": "Een kopie van mijn Vikunja gegevens opvragen",
"success": "Je hebt met succes je Vikunja Data aangevraagd! We sturen je een e-mail zodra het klaar is om te downloaden.", "success": "Je hebt met succes je Vikunja Data aangevraagd! We sturen je een e-mail zodra het klaar is om te downloaden.",
@ -165,14 +163,18 @@
} }
}, },
"project": { "project": {
"archived": "This project is archived. It is not possible to create new or edit tasks for it.", "archivedMessage": "This project is archived. It is not possible to create new or edit tasks for it.",
"archived": "Archived",
"showArchived": "Show Archived",
"title": "Project Title", "title": "Project Title",
"color": "Color", "color": "Color",
"projects": "Projects", "projects": "Projects",
"parent": "Parent Project",
"search": "Type to search for a project…", "search": "Type to search for a project…",
"searchSelect": "Click or press enter to select this project", "searchSelect": "Click or press enter to select this project",
"shared": "Shared Projects", "shared": "Shared Projects",
"noDescriptionAvailable": "No project description is available.", "noDescriptionAvailable": "No project description is available.",
"inboxTitle": "Inbox",
"create": { "create": {
"header": "New project", "header": "New project",
"titlePlaceholder": "The project's title goes here…", "titlePlaceholder": "The project's title goes here…",
@ -210,7 +212,7 @@
"duplicate": { "duplicate": {
"title": "Duplicate this project", "title": "Duplicate this project",
"label": "Duplicate", "label": "Duplicate",
"text": "Select a namespace which should hold the duplicated project:", "text": "Select a parent project which should hold the duplicated project:",
"success": "The project was successfully duplicated." "success": "The project was successfully duplicated."
}, },
"edit": { "edit": {
@ -321,67 +323,6 @@
} }
} }
}, },
"namespace": {
"title": "Namespaces & Projects",
"namespace": "Namespace",
"showArchived": "Toon gearchiveerd",
"noneAvailable": "Je hebt op dit moment geen Namespaces.",
"unarchive": "Archivering opheffen",
"archived": "Gearchiveerd",
"noProjects": "This namespace does not contain any projects.",
"createProject": "Create a new project in this namespace.",
"namespaces": "Namespaces",
"search": "Begin met typen om een Namespace te zoeken…",
"create": {
"title": "Nieuwe namespace",
"titleRequired": "Voer een titel in.",
"explanation": "A namespace is a collection of projects you can share and use to organize your projects with. In fact, every project belongs to a namespace.",
"tooltip": "Wat is een namespace?",
"success": "De Namespace is succesvol gemaakt."
},
"archive": {
"titleArchive": "Archiveer \"{namespace}\"",
"titleUnarchive": "Archivering \"{namespace}\" ongedaan maken",
"archiveText": "You won't be able to edit this namespace or create new projects until you un-archive it. This will also archive all projects in this namespace.",
"unarchiveText": "You will be able to create new projects or edit it.",
"success": "The namespace was successfully archived.",
"unarchiveSuccess": "The namespace was successfully un-archived.",
"description": "If a namespace is archived, you cannot create new projects or edit it."
},
"delete": {
"title": "\"{namespace}\" verwijderen",
"text1": "Weet je zeker dat je deze Namespace en alle inhoud ervan wilt verwijderen?",
"text2": "This includes all projects and tasks and CANNOT BE UNDONE!",
"success": "De Namespace is succesvol verwijderd."
},
"edit": {
"title": "Bewerk \"{namespace}\"",
"success": "The namespace was successfully updated."
},
"share": {
"title": "\"{namespace}\" delen"
},
"attributes": {
"title": "Namespace titel",
"titlePlaceholder": "The namespace title goes here…",
"description": "Beschrijving",
"descriptionPlaceholder": "The namespaces description goes here…",
"color": "Kleur",
"archived": "Is gearchiveerd",
"isArchived": "This namespace is archived"
},
"pseudo": {
"sharedProjects": {
"title": "Shared Projects"
},
"favorites": {
"title": "Favorieten"
},
"savedFilters": {
"title": "Filters"
}
}
},
"filters": { "filters": {
"title": "Filters", "title": "Filters",
"clear": "Clear Filters", "clear": "Clear Filters",
@ -403,7 +344,7 @@
}, },
"create": { "create": {
"title": "New Saved Filter", "title": "New Saved Filter",
"description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed. Once created, it will appear in a special namespace.", "description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed.",
"action": "Create new saved filter", "action": "Create new saved filter",
"titleRequired": "Please provide a title for the filter." "titleRequired": "Please provide a title for the filter."
}, },
@ -674,19 +615,13 @@
"updated": "Bijgewerkt" "updated": "Bijgewerkt"
}, },
"subscription": { "subscription": {
"subscribedProjectThroughParentNamespace": "You can't unsubscribe here because you are subscribed to this project through its namespace.",
"subscribedTaskThroughParentNamespace": "You can't unsubscribe here because you are subscribed to this task through its namespace.",
"subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.", "subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.",
"subscribedNamespace": "You are currently subscribed to this namespace and will receive notifications for changes.",
"notSubscribedNamespace": "You are not subscribed to this namespace and won't receive notifications for changes.",
"subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.", "subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.",
"notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.", "notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.",
"subscribedTask": "You are currently subscribed to this task and will receive notifications for changes.", "subscribedTask": "You are currently subscribed to this task and will receive notifications for changes.",
"notSubscribedTask": "You are not subscribed to this task and won't receive notifications for changes.", "notSubscribedTask": "You are not subscribed to this task and won't receive notifications for changes.",
"subscribe": "Subscribe", "subscribe": "Subscribe",
"unsubscribe": "Unsubscribe", "unsubscribe": "Unsubscribe",
"subscribeSuccessNamespace": "You are now subscribed to this namespace",
"unsubscribeSuccessNamespace": "You are now unsubscribed to this namespace",
"subscribeSuccessProject": "You are now subscribed to this project", "subscribeSuccessProject": "You are now subscribed to this project",
"unsubscribeSuccessProject": "You are now unsubscribed to this project", "unsubscribeSuccessProject": "You are now unsubscribed to this project",
"subscribeSuccessTask": "You are now subscribed to this task", "subscribeSuccessTask": "You are now subscribed to this task",
@ -763,7 +698,6 @@
"searchPlaceholder": "Type search for a new task to add as related…", "searchPlaceholder": "Type search for a new task to add as related…",
"createPlaceholder": "Voeg dit toe als nieuwe gerelateerde taak", "createPlaceholder": "Voeg dit toe als nieuwe gerelateerde taak",
"differentProject": "This task belongs to a different project.", "differentProject": "This task belongs to a different project.",
"differentNamespace": "This task belongs to a different namespace.",
"noneYet": "Nog geen taakrelaties.", "noneYet": "Nog geen taakrelaties.",
"delete": "Taak relatie verwijderen", "delete": "Taak relatie verwijderen",
"deleteText1": "Weet je zeker dat je deze taakrelatie wilt verwijderen?", "deleteText1": "Weet je zeker dat je deze taakrelatie wilt verwijderen?",
@ -848,19 +782,19 @@
"delete": { "delete": {
"header": "Verwijder het team", "header": "Verwijder het team",
"text1": "Are you sure you want to delete this team and all of its members?", "text1": "Are you sure you want to delete this team and all of its members?",
"text2": "All team members will lose access to projects and namespaces shared with this team. This CANNOT BE UNDONE!", "text2": "All team members will lose access to projects shared with this team. This CANNOT BE UNDONE!",
"success": "The team was successfully deleted." "success": "The team was successfully deleted."
}, },
"deleteUser": { "deleteUser": {
"header": "Verwijder een gebruiker uit het team", "header": "Verwijder een gebruiker uit het team",
"text1": "Weet je zeker dat je deze gebruiker wilt verwijderen uit het team?", "text1": "Weet je zeker dat je deze gebruiker wilt verwijderen uit het team?",
"text2": "They will lose access to all projects and namespaces this team has access to. This CANNOT BE UNDONE!", "text2": "They will lose access to all projects this team has access to. This CANNOT BE UNDONE!",
"success": "The user was successfully deleted from the team." "success": "The user was successfully deleted from the team."
}, },
"leave": { "leave": {
"title": "Leave team", "title": "Leave team",
"text1": "Are you sure you want to leave this team?", "text1": "Are you sure you want to leave this team?",
"text2": "You will lose access to all projects and namespaces this team has access to. If you change your mind you'll need a team admin to add you again.", "text2": "You will lose access to all projects this team has access to. If you change your mind you'll need a team admin to add you again.",
"success": "You have successfully left the team." "success": "You have successfully left the team."
} }
}, },
@ -894,7 +828,10 @@
"color": "Change the color of this task", "color": "Change the color of this task",
"move": "Move this task to another project", "move": "Move this task to another project",
"reminder": "Manage reminders of this task", "reminder": "Manage reminders of this task",
"description": "Toggle editing of the task description" "description": "Toggle editing of the task description",
"delete": "Delete this task",
"priority": "Change the priority of this task",
"favorite": "Mark this task as favorite / unfavorite"
}, },
"project": { "project": {
"title": "Project Views", "title": "Project Views",
@ -907,9 +844,9 @@
"title": "Navigation", "title": "Navigation",
"overview": "Navigate to overview", "overview": "Navigate to overview",
"upcoming": "Navigate to upcoming tasks", "upcoming": "Navigate to upcoming tasks",
"namespaces": "Navigate to namespaces & projects",
"labels": "Navigate to labels", "labels": "Navigate to labels",
"teams": "Navigate to teams" "teams": "Navigate to teams",
"projects": "Navigate to projects"
} }
}, },
"update": { "update": {
@ -924,7 +861,8 @@
"unarchive": "Archivering opheffen", "unarchive": "Archivering opheffen",
"setBackground": "Achtergrond instellen", "setBackground": "Achtergrond instellen",
"share": "Delen", "share": "Delen",
"newProject": "New project" "newProject": "New project",
"createProject": "Create project"
}, },
"apiConfig": { "apiConfig": {
"url": "Vikunja URL", "url": "Vikunja URL",
@ -943,7 +881,7 @@
"notification": { "notification": {
"title": "Notificaties", "title": "Notificaties",
"none": "Je hebt geen meldingen. Fijne dag!", "none": "Je hebt geen meldingen. Fijne dag!",
"explainer": "Notifications will appear here when actions on namespaces, projects or tasks you subscribed to happen." "explainer": "Notifications will appear here when actions projects or tasks you subscribed to happen."
}, },
"quickActions": { "quickActions": {
"commands": "Commands", "commands": "Commands",
@ -954,14 +892,12 @@
"teams": "Teams", "teams": "Teams",
"newProject": "Enter the title of the new project…", "newProject": "Enter the title of the new project…",
"newTask": "Enter the title of the new task…", "newTask": "Enter the title of the new task…",
"newNamespace": "Enter the title of the new namespace…",
"newTeam": "Enter the name of the new team…", "newTeam": "Enter the name of the new team…",
"createTask": "Create a task in the current project ({title})", "createTask": "Create a task in the current project ({title})",
"createProject": "Create a project in the current namespace ({title})", "createProject": "Create a project",
"cmds": { "cmds": {
"newTask": "Nieuwe taak", "newTask": "Nieuwe taak",
"newProject": "New project", "newProject": "New project",
"newNamespace": "Nieuwe namespace",
"newTeam": "Nieuw team" "newTeam": "Nieuw team"
} }
}, },
@ -1017,16 +953,9 @@
"4017": "Invalid task filter comparator.", "4017": "Invalid task filter comparator.",
"4018": "Invalid task filter concatenator.", "4018": "Invalid task filter concatenator.",
"4019": "Ongeldige taakfilter waarde.", "4019": "Ongeldige taakfilter waarde.",
"5001": "Deze Namespace bestaat niet.",
"5003": "Je hebt geen toegang tot de opgegeven Namespace.",
"5006": "De naam van de namespace mag niet leeg zijn.",
"5009": "You need to have namespace read access to perform that action.",
"5010": "This team does not have access to that namespace.",
"5011": "This user has already access to that namespace.",
"5012": "The namespace is archived and can therefore only be accessed read only.",
"6001": "The team name cannot be empty.", "6001": "The team name cannot be empty.",
"6002": "Het team bestaat niet.", "6002": "Het team bestaat niet.",
"6004": "The team already has access to that namespace or project.", "6004": "The team already has access to that project.",
"6005": "The user is already a member of that team.", "6005": "The user is already a member of that team.",
"6006": "Kan het laatste teamlid niet verwijderen.", "6006": "Kan het laatste teamlid niet verwijderen.",
"6007": "The team does not have access to the project to perform that action.", "6007": "The team does not have access to the project to perform that action.",
@ -1053,4 +982,4 @@
"frontendVersion": "Frontend versie: {version}", "frontendVersion": "Frontend versie: {version}",
"apiVersion": "API Versie: {version}" "apiVersion": "API Versie: {version}"
} }
} }

View File

@ -6,9 +6,7 @@
"welcomeEvening": "God Morgen {username}!", "welcomeEvening": "God Morgen {username}!",
"lastViewed": "Sist sett", "lastViewed": "Sist sett",
"project": { "project": {
"newText": "Du kan opprette en ny liste for dine nye oppgaver:", "importText": "Import your projects and tasks from other services into Vikunja:",
"new": "Nytt prosjekt",
"importText": "Eller importer lister og oppgaver fra andre tjenester til Vikunja:",
"import": "Importer dine data til Vikunja" "import": "Importer dine data til Vikunja"
} }
}, },
@ -143,7 +141,7 @@
}, },
"deletion": { "deletion": {
"title": "Slett kontoen din", "title": "Slett kontoen din",
"text1": "Sletting av din konto er permanent og kan ikke angres. Vi vil slette alle dine navneområder og prosjekter, oppgaver og alt forbundet med den.", "text1": "The deletion of your account is permanent and cannot be undone. We will delete all your projects, tasks and everything associated with it.",
"text2": "For å fortsette, skriv inn passordet ditt. Du vil motta en e-post med ytterligere instruksjoner.", "text2": "For å fortsette, skriv inn passordet ditt. Du vil motta en e-post med ytterligere instruksjoner.",
"confirm": "Slett min konto", "confirm": "Slett min konto",
"requestSuccess": "Forespørselen var vellykket. Du vil motta en e-post med ytterligere instruksjoner.", "requestSuccess": "Forespørselen var vellykket. Du vil motta en e-post med ytterligere instruksjoner.",
@ -157,7 +155,7 @@
}, },
"export": { "export": {
"title": "Eksporter dine kontodata", "title": "Eksporter dine kontodata",
"description": "Du kan be om en kopi av alle Vikunja dataene dine. Dette inkluderer navneområder, lister, oppgaver og alt tilknyttet dem.", "description": "You can request a copy of all your Vikunja data. This includes Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
"descriptionPasswordRequired": "Skriv inn passordet for å fortsette:", "descriptionPasswordRequired": "Skriv inn passordet for å fortsette:",
"request": "Be om kopi av mine Vikunja Data", "request": "Be om kopi av mine Vikunja Data",
"success": "Du har spurt om dine Vikunja data! Vi sender deg en e-post når den er klar til å laste ned.", "success": "Du har spurt om dine Vikunja data! Vi sender deg en e-post når den er klar til å laste ned.",
@ -165,14 +163,18 @@
} }
}, },
"project": { "project": {
"archived": "Dette prosjektet er arkivert. Det er ikke mulig å opprette nye eller redigere oppgaver for det.", "archivedMessage": "This project is archived. It is not possible to create new or edit tasks for it.",
"archived": "Archived",
"showArchived": "Show Archived",
"title": "Prosjekt tittel", "title": "Prosjekt tittel",
"color": "Farger", "color": "Farger",
"projects": "Prosjekter", "projects": "Prosjekter",
"parent": "Parent Project",
"search": "Tast for å søke etter et prosjekt…", "search": "Tast for å søke etter et prosjekt…",
"searchSelect": "Klikk eller trykk enter for å velge dette prosjektet", "searchSelect": "Klikk eller trykk enter for å velge dette prosjektet",
"shared": "Delte prosjekter", "shared": "Delte prosjekter",
"noDescriptionAvailable": "Ingen prosjektbeskrivelse er tilgjengelig.", "noDescriptionAvailable": "Ingen prosjektbeskrivelse er tilgjengelig.",
"inboxTitle": "Inbox",
"create": { "create": {
"header": "Nytt prosjekt", "header": "Nytt prosjekt",
"titlePlaceholder": "Prosjektets tittel er her…", "titlePlaceholder": "Prosjektets tittel er her…",
@ -210,7 +212,7 @@
"duplicate": { "duplicate": {
"title": "Dupliser dette prosjektet", "title": "Dupliser dette prosjektet",
"label": "Dupliser", "label": "Dupliser",
"text": "Velg et navneområde som skal holde det dupliserte prosjektet:", "text": "Select a parent project which should hold the duplicated project:",
"success": "Prosjektet ble duplisert." "success": "Prosjektet ble duplisert."
}, },
"edit": { "edit": {
@ -321,67 +323,6 @@
} }
} }
}, },
"namespace": {
"title": "Navneområder & lister",
"namespace": "Navneområde",
"showArchived": "Vis arkiverte",
"noneAvailable": "Du har ingen navneområder akkurat nå.",
"unarchive": "Av-arkiver",
"archived": "Arkivert",
"noProjects": "Dette navneområdet inneholder ikke noen prosjekter.",
"createProject": "Opprett et nytt prosjekt i dette navneområdet.",
"namespaces": "Navnerom",
"search": "Skriv for å søke etter en etikett…",
"create": {
"title": "Nytt navneområde",
"titleRequired": "Angi den nye tittelen.",
"explanation": "Et navneområde er en samling av lister du kan dele og bruke til å organisere listene dine med. I realiteten hører hver liste til et navneområde.",
"tooltip": "Hva er et navneområde?",
"success": "Navneområdet ble opprettet."
},
"archive": {
"titleArchive": "Arkiv \"{namespace}\"",
"titleUnarchive": "Av-Arkiv \"{namespace}\"",
"archiveText": "Du vil ikke kunne redigere dette navneområdet eller opprette nye lister før du avlaster arkivet. Dette vil også arkivere alle lister i dette navneområdet.",
"unarchiveText": "Du vil kunne opprette nye oppgaver eller redigere den.",
"success": "Navnerommet ble arkivert.",
"unarchiveSuccess": "Navnerommet ble vellykket fjernet fra arkivet.",
"description": "Hvis navneområdet er arkivert, kan du ikke opprette nye lister eller redigere det."
},
"delete": {
"title": "Slett \"{namespace}",
"text1": "Er du sikker på at du vil slette dette navneområdet og alt innholdet?",
"text2": "Dette inkluderer alle oppgaver og KAN IKKE ANGRES!",
"success": "Navnområdet ble slettet."
},
"edit": {
"title": "Rediger \"{namespace}",
"success": "Navnerommet ble oppdatert."
},
"share": {
"title": "Del \"{namespace}"
},
"attributes": {
"title": "Navneområdes Tittel",
"titlePlaceholder": "Navneområdets tittel går her…",
"description": "Beskrivelse",
"descriptionPlaceholder": "Beskrivelsen av navneområdene gis her…",
"color": "Farger",
"archived": "Arkivert",
"isArchived": "Dette navneområdet er arkivert"
},
"pseudo": {
"sharedProjects": {
"title": "Delte prosjekter"
},
"favorites": {
"title": "Favoritter"
},
"savedFilters": {
"title": "Filtre"
}
}
},
"filters": { "filters": {
"title": "Filtre", "title": "Filtre",
"clear": "Fjern filtre", "clear": "Fjern filtre",
@ -403,7 +344,7 @@
}, },
"create": { "create": {
"title": "Nytt lagret filter", "title": "Nytt lagret filter",
"description": "Et lagret filter er en virtuell liste som beregnes fra et sett med filtre hver gang det åpnes. Når du er opprettet, vil det vises i et eget navneområde.", "description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed.",
"action": "Opprett nytt filter", "action": "Opprett nytt filter",
"titleRequired": "Skriv inn en tittel for filteret." "titleRequired": "Skriv inn en tittel for filteret."
}, },
@ -674,19 +615,13 @@
"updated": "Oppdatert" "updated": "Oppdatert"
}, },
"subscription": { "subscription": {
"subscribedProjectThroughParentNamespace": "Du kan ikke slutte å abonnere her fordi du abonnerer på denne listen gjennom dens navneområde.",
"subscribedTaskThroughParentNamespace": "Du kan ikke slutte å abonnere her fordi du abonnerer på denne oppgaven gjennom navneområdet.",
"subscribedTaskThroughParentProject": "Du kan ikke melde deg ut her fordi du abonnerer på denne oppgaven gjennom prosjektet.", "subscribedTaskThroughParentProject": "Du kan ikke melde deg ut her fordi du abonnerer på denne oppgaven gjennom prosjektet.",
"subscribedNamespace": "Du abonnerer for øyeblikket på dette navneområdet og vil motta varsler for endringer.",
"notSubscribedNamespace": "Du abonnerer ikke på dette navneområdet og vil ikke motta varsler for endringer.",
"subscribedProject": "Du abonnerer for øyeblikket på dette prosjektet og vil motta varsler for endringer.", "subscribedProject": "Du abonnerer for øyeblikket på dette prosjektet og vil motta varsler for endringer.",
"notSubscribedProject": "Du abonnerer ikke på dette prosjektet og vil ikke motta varsler for endringer.", "notSubscribedProject": "Du abonnerer ikke på dette prosjektet og vil ikke motta varsler for endringer.",
"subscribedTask": "Du abonnerer for øyeblikket på denne oppgaven og vil motta varsler for endringer.", "subscribedTask": "Du abonnerer for øyeblikket på denne oppgaven og vil motta varsler for endringer.",
"notSubscribedTask": "Du abonnerer ikke på denne oppgaven og vil ikke motta varsler for endringer.", "notSubscribedTask": "Du abonnerer ikke på denne oppgaven og vil ikke motta varsler for endringer.",
"subscribe": "Abonnerer", "subscribe": "Abonnerer",
"unsubscribe": "Avslutt abonnement", "unsubscribe": "Avslutt abonnement",
"subscribeSuccessNamespace": "Du abonnerer nå på dette navneområdet",
"unsubscribeSuccessNamespace": "Du blir nå avmeldt dette navneområdet",
"subscribeSuccessProject": "Du abonnerer nå på dette prosjektet", "subscribeSuccessProject": "Du abonnerer nå på dette prosjektet",
"unsubscribeSuccessProject": "Du har nå avsluttet abonnementet for dette prosjektet", "unsubscribeSuccessProject": "Du har nå avsluttet abonnementet for dette prosjektet",
"subscribeSuccessTask": "Du abonnerer nå på denne oppgaven", "subscribeSuccessTask": "Du abonnerer nå på denne oppgaven",
@ -763,7 +698,6 @@
"searchPlaceholder": "Skriv søk etter en ny oppgave å legge til som relatert…", "searchPlaceholder": "Skriv søk etter en ny oppgave å legge til som relatert…",
"createPlaceholder": "Legg til denne som ny relatert oppgave", "createPlaceholder": "Legg til denne som ny relatert oppgave",
"differentProject": "Denne oppgaven tilhører et annet prosjekt.", "differentProject": "Denne oppgaven tilhører et annet prosjekt.",
"differentNamespace": "Denne oppgaven tilhører en annen navneområde.",
"noneYet": "Ingen arbeidsrelasjoner ennå.", "noneYet": "Ingen arbeidsrelasjoner ennå.",
"delete": "Slett relasjon", "delete": "Slett relasjon",
"deleteText1": "Er du sikker på at du vil slette denne relasjonen?", "deleteText1": "Er du sikker på at du vil slette denne relasjonen?",
@ -848,19 +782,19 @@
"delete": { "delete": {
"header": "Slett gruppen", "header": "Slett gruppen",
"text1": "Er du sikker på at du vil slette denne gruppen og alle dets medlemmer?", "text1": "Er du sikker på at du vil slette denne gruppen og alle dets medlemmer?",
"text2": "Alle teammedlemmer vil miste tilgang til prosjekter og navneområder som deles med dette teamet. KAN IKKE ANGRES!", "text2": "All team members will lose access to projects shared with this team. This CANNOT BE UNDONE!",
"success": "Gruppen ble slettet." "success": "Gruppen ble slettet."
}, },
"deleteUser": { "deleteUser": {
"header": "Fjerne en bruker fra gruppen", "header": "Fjerne en bruker fra gruppen",
"text1": "Er du sikker på at du vil fjerne bruker fra denne gruppen?", "text1": "Er du sikker på at du vil fjerne bruker fra denne gruppen?",
"text2": "De vil miste tilgang til alle prosjekter og namespaces dette teamet har tilgang til. Dette KAN IKKE ANGRES!", "text2": "They will lose access to all projects this team has access to. This CANNOT BE UNDONE!",
"success": "Brukeren ble slettet fra gruppen." "success": "Brukeren ble slettet fra gruppen."
}, },
"leave": { "leave": {
"title": "Forlat gruppen", "title": "Forlat gruppen",
"text1": "Er du sikker på at du vil forlate denne gruppen?", "text1": "Er du sikker på at du vil forlate denne gruppen?",
"text2": "Du vil miste tilgang til alle prosjekter og namespaces dette teamet har tilgang til. Hvis du ombestemmer deg, må du ha en lagadministrator for å legge deg til igjen.", "text2": "You will lose access to all projects this team has access to. If you change your mind you'll need a team admin to add you again.",
"success": "Du har forlatt gruppen." "success": "Du har forlatt gruppen."
} }
}, },
@ -894,7 +828,10 @@
"color": "Endre fargen på denne oppgaven", "color": "Endre fargen på denne oppgaven",
"move": "Flytt denne oppgaven til et annet prosjekt", "move": "Flytt denne oppgaven til et annet prosjekt",
"reminder": "Behandle påminnelser om denne oppgaven", "reminder": "Behandle påminnelser om denne oppgaven",
"description": "Veksle redigering av oppgavebeskrivelsen" "description": "Veksle redigering av oppgavebeskrivelsen",
"delete": "Delete this task",
"priority": "Change the priority of this task",
"favorite": "Mark this task as favorite / unfavorite"
}, },
"project": { "project": {
"title": "Prosjektvisning", "title": "Prosjektvisning",
@ -907,9 +844,9 @@
"title": "Navigasjon", "title": "Navigasjon",
"overview": "Naviger til oversikt", "overview": "Naviger til oversikt",
"upcoming": "Gå til kommende oppgaver", "upcoming": "Gå til kommende oppgaver",
"namespaces": "Gå til navneområder & prosjekter",
"labels": "Naviger til etiketter", "labels": "Naviger til etiketter",
"teams": "Naviger til gruppe" "teams": "Naviger til gruppe",
"projects": "Navigate to projects"
} }
}, },
"update": { "update": {
@ -924,7 +861,8 @@
"unarchive": "Av-arkiver", "unarchive": "Av-arkiver",
"setBackground": "Bruk som bakgrunn", "setBackground": "Bruk som bakgrunn",
"share": "Del", "share": "Del",
"newProject": "Nytt prosjekt" "newProject": "Nytt prosjekt",
"createProject": "Create project"
}, },
"apiConfig": { "apiConfig": {
"url": "Vikunja URL", "url": "Vikunja URL",
@ -943,7 +881,7 @@
"notification": { "notification": {
"title": "Varsler", "title": "Varsler",
"none": "Du har ingen varsler på dette tidspunktet!", "none": "Du har ingen varsler på dette tidspunktet!",
"explainer": "Varsler vil vises her når handlinger på navneområder, prosjekter, lister eller oppgaver du abonnerer på." "explainer": "Notifications will appear here when actions projects or tasks you subscribed to happen."
}, },
"quickActions": { "quickActions": {
"commands": "Kommandoer", "commands": "Kommandoer",
@ -954,14 +892,12 @@
"teams": "Grupper", "teams": "Grupper",
"newProject": "Skriv tittelen på det nye prosjektet…", "newProject": "Skriv tittelen på det nye prosjektet…",
"newTask": "Skriv tittelen på den nye oppgaven…", "newTask": "Skriv tittelen på den nye oppgaven…",
"newNamespace": "Skriv inn tittelen på det nye navneområdet…",
"newTeam": "Skriv inn navnet på den nye gruppen…", "newTeam": "Skriv inn navnet på den nye gruppen…",
"createTask": "Opprett en oppgave i det gjeldende prosjektet ({title})", "createTask": "Opprett en oppgave i det gjeldende prosjektet ({title})",
"createProject": "Opprett et prosjekt i gjeldende navneområde ({title})", "createProject": "Create a project",
"cmds": { "cmds": {
"newTask": "Ny oppgave", "newTask": "Ny oppgave",
"newProject": "Nytt prosjekt", "newProject": "Nytt prosjekt",
"newNamespace": "Nytt navneområde",
"newTeam": "Ny gruppe" "newTeam": "Ny gruppe"
} }
}, },
@ -1017,16 +953,9 @@
"4017": "Ugyldig oppgave filter.", "4017": "Ugyldig oppgave filter.",
"4018": "Ugyldig oppgave filter.", "4018": "Ugyldig oppgave filter.",
"4019": "Ugyldig oppgave filterverdi.", "4019": "Ugyldig oppgave filterverdi.",
"5001": "Navneområdet finnes ikke.",
"5003": "Du har ikke tilgang til det angitte navneområdet.",
"5006": "Navneområde-navnet kan ikke være tomt.",
"5009": "Du må ha lesetilgang til navneområdet for å utføre den handlingen.",
"5010": "Denne gruppen har ikke tilgang til det navneområdet.",
"5011": "Denne brukeren har allerede tilgang til det navneområdet.",
"5012": "Navneområdet er arkivert og kan derfor kun leses på.",
"6001": "Gruppe nanvet kan ikke være tomt.", "6001": "Gruppe nanvet kan ikke være tomt.",
"6002": "Gruppen finnes ikke.", "6002": "Gruppen finnes ikke.",
"6004": "Teamet har allerede tilgang til det navneområdet eller prosjektet.", "6004": "The team already has access to that project.",
"6005": "Brukeren er allerede medlem av gruppen.", "6005": "Brukeren er allerede medlem av gruppen.",
"6006": "Kan ikke slette siste gruppemedlem.", "6006": "Kan ikke slette siste gruppemedlem.",
"6007": "Gruppen har ikke tilgang til prosjektet for å utføre den handlingen.", "6007": "Gruppen har ikke tilgang til prosjektet for å utføre den handlingen.",
@ -1053,4 +982,4 @@
"frontendVersion": "Frontend versjon: {version}", "frontendVersion": "Frontend versjon: {version}",
"apiVersion": "API versjon: {version}" "apiVersion": "API versjon: {version}"
} }
} }

View File

@ -6,9 +6,7 @@
"welcomeEvening": "Good Evening {username}!", "welcomeEvening": "Good Evening {username}!",
"lastViewed": "Ostatnio oglądane", "lastViewed": "Ostatnio oglądane",
"project": { "project": {
"newText": "You can create a new project for your new tasks:", "importText": "Import your projects and tasks from other services into Vikunja:",
"new": "New project",
"importText": "Or import your projects and tasks from other services into Vikunja:",
"import": "Import your data into Vikunja" "import": "Import your data into Vikunja"
} }
}, },
@ -143,7 +141,7 @@
}, },
"deletion": { "deletion": {
"title": "Usuń swoje konto Vikunja", "title": "Usuń swoje konto Vikunja",
"text1": "The deletion of your account is permanent and cannot be undone. We will delete all your namespaces, projects, tasks and everything associated with it.", "text1": "The deletion of your account is permanent and cannot be undone. We will delete all your projects, tasks and everything associated with it.",
"text2": "Aby kontynuować, wprowadź swoje hasło. Otrzymasz wiadomość e-mail z dalszymi instrukcjami.", "text2": "Aby kontynuować, wprowadź swoje hasło. Otrzymasz wiadomość e-mail z dalszymi instrukcjami.",
"confirm": "Usuń moje konto", "confirm": "Usuń moje konto",
"requestSuccess": "Żądanie powiodło się. Otrzymasz wiadomość e-mail z dalszymi instrukcjami.", "requestSuccess": "Żądanie powiodło się. Otrzymasz wiadomość e-mail z dalszymi instrukcjami.",
@ -157,7 +155,7 @@
}, },
"export": { "export": {
"title": "Eksportuj swoje dane Vikunja", "title": "Eksportuj swoje dane Vikunja",
"description": "You can request a copy of all your Vikunja data. This include Namespaces, Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.", "description": "You can request a copy of all your Vikunja data. This includes Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
"descriptionPasswordRequired": "Wprowadź hasło, aby kontynuować:", "descriptionPasswordRequired": "Wprowadź hasło, aby kontynuować:",
"request": "Generuj kopię moich danych Vikunja", "request": "Generuj kopię moich danych Vikunja",
"success": "Pomyślnie zażądałeś danych Vikunja! Wyślemy Ci e-mail, gdy będą gotowe do pobrania.", "success": "Pomyślnie zażądałeś danych Vikunja! Wyślemy Ci e-mail, gdy będą gotowe do pobrania.",
@ -165,14 +163,18 @@
} }
}, },
"project": { "project": {
"archived": "This project is archived. It is not possible to create new or edit tasks for it.", "archivedMessage": "This project is archived. It is not possible to create new or edit tasks for it.",
"archived": "Archived",
"showArchived": "Show Archived",
"title": "Project Title", "title": "Project Title",
"color": "Color", "color": "Color",
"projects": "Projects", "projects": "Projects",
"parent": "Parent Project",
"search": "Type to search for a project…", "search": "Type to search for a project…",
"searchSelect": "Click or press enter to select this project", "searchSelect": "Click or press enter to select this project",
"shared": "Shared Projects", "shared": "Shared Projects",
"noDescriptionAvailable": "No project description is available.", "noDescriptionAvailable": "No project description is available.",
"inboxTitle": "Inbox",
"create": { "create": {
"header": "New project", "header": "New project",
"titlePlaceholder": "The project's title goes here…", "titlePlaceholder": "The project's title goes here…",
@ -210,7 +212,7 @@
"duplicate": { "duplicate": {
"title": "Duplicate this project", "title": "Duplicate this project",
"label": "Duplicate", "label": "Duplicate",
"text": "Select a namespace which should hold the duplicated project:", "text": "Select a parent project which should hold the duplicated project:",
"success": "The project was successfully duplicated." "success": "The project was successfully duplicated."
}, },
"edit": { "edit": {
@ -321,67 +323,6 @@
} }
} }
}, },
"namespace": {
"title": "Namespaces & Projects",
"namespace": "Sekcja",
"showArchived": "Pokaż zarchiwizowane",
"noneAvailable": "W tej chwili nie masz żadnych sekcji.",
"unarchive": "Cofnij archiwizację",
"archived": "Zarchiwizowane",
"noProjects": "This namespace does not contain any projects.",
"createProject": "Create a new project in this namespace.",
"namespaces": "Sekcje",
"search": "Wpisz, aby wyszukać sekcję…",
"create": {
"title": "Nowa sekcja",
"titleRequired": "Proszę, podaj tytuł.",
"explanation": "A namespace is a collection of projects you can share and use to organize your projects with. In fact, every project belongs to a namespace.",
"tooltip": "Co to jest sekcja?",
"success": "Sekcja została pomyślnie utworzona."
},
"archive": {
"titleArchive": "Archiwizuj \"{namespace}\"",
"titleUnarchive": "Cofnij archiwizację \"{namespace}\"",
"archiveText": "You won't be able to edit this namespace or create new projects until you un-archive it. This will also archive all projects in this namespace.",
"unarchiveText": "You will be able to create new projects or edit it.",
"success": "Sekcja została pomyślnie zarchiwizowana.",
"unarchiveSuccess": "Archiwizacja sekcji została pomyślnie cofnięta.",
"description": "If a namespace is archived, you cannot create new projects or edit it."
},
"delete": {
"title": "Usuń \"{namespace}\"",
"text1": "Czy na pewno chcesz usunąć tę sekcję i całą jej zawartość?",
"text2": "This includes all projects and tasks and CANNOT BE UNDONE!",
"success": "Sekcja została pomyślnie usunięta."
},
"edit": {
"title": "Edytuj \"{namespace}\"",
"success": "Sekcja została pomyślnie zaktualizowana."
},
"share": {
"title": "Udostępnij \"{namespace}\""
},
"attributes": {
"title": "Tytuł sekcji",
"titlePlaceholder": "Tu wpisz tytuł sekcji…",
"description": "Opis",
"descriptionPlaceholder": "Tu wpisz opis sekcji…",
"color": "Kolor",
"archived": "Archiwizacja",
"isArchived": "Ta sekcja jest zarchiwizowana"
},
"pseudo": {
"sharedProjects": {
"title": "Shared Projects"
},
"favorites": {
"title": "Ulubione"
},
"savedFilters": {
"title": "Filtry"
}
}
},
"filters": { "filters": {
"title": "Filtry", "title": "Filtry",
"clear": "Wyczyść filtry", "clear": "Wyczyść filtry",
@ -403,7 +344,7 @@
}, },
"create": { "create": {
"title": "Nowy filtr stały", "title": "Nowy filtr stały",
"description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed. Once created, it will appear in a special namespace.", "description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed.",
"action": "Utwórz nowy filtr stały", "action": "Utwórz nowy filtr stały",
"titleRequired": "Please provide a title for the filter." "titleRequired": "Please provide a title for the filter."
}, },
@ -674,19 +615,13 @@
"updated": "Zaktualizowano" "updated": "Zaktualizowano"
}, },
"subscription": { "subscription": {
"subscribedProjectThroughParentNamespace": "You can't unsubscribe here because you are subscribed to this project through its namespace.",
"subscribedTaskThroughParentNamespace": "You can't unsubscribe here because you are subscribed to this task through its namespace.",
"subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.", "subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.",
"subscribedNamespace": "You are currently subscribed to this namespace and will receive notifications for changes.",
"notSubscribedNamespace": "You are not subscribed to this namespace and won't receive notifications for changes.",
"subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.", "subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.",
"notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.", "notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.",
"subscribedTask": "You are currently subscribed to this task and will receive notifications for changes.", "subscribedTask": "You are currently subscribed to this task and will receive notifications for changes.",
"notSubscribedTask": "You are not subscribed to this task and won't receive notifications for changes.", "notSubscribedTask": "You are not subscribed to this task and won't receive notifications for changes.",
"subscribe": "Subskrybuj", "subscribe": "Subskrybuj",
"unsubscribe": "Anuluj subskrypcję", "unsubscribe": "Anuluj subskrypcję",
"subscribeSuccessNamespace": "You are now subscribed to this namespace",
"unsubscribeSuccessNamespace": "You are now unsubscribed to this namespace",
"subscribeSuccessProject": "You are now subscribed to this project", "subscribeSuccessProject": "You are now subscribed to this project",
"unsubscribeSuccessProject": "You are now unsubscribed to this project", "unsubscribeSuccessProject": "You are now unsubscribed to this project",
"subscribeSuccessTask": "You are now subscribed to this task", "subscribeSuccessTask": "You are now subscribed to this task",
@ -763,7 +698,6 @@
"searchPlaceholder": "Wpisz, aby wyszukać zadanie, które chcesz dodać jako powiązane…", "searchPlaceholder": "Wpisz, aby wyszukać zadanie, które chcesz dodać jako powiązane…",
"createPlaceholder": "Dodaj jako nowe powiązane zadanie", "createPlaceholder": "Dodaj jako nowe powiązane zadanie",
"differentProject": "This task belongs to a different project.", "differentProject": "This task belongs to a different project.",
"differentNamespace": "To zadanie należy do innej sekcji.",
"noneYet": "Nie ma jeszcze powiązanych zadań.", "noneYet": "Nie ma jeszcze powiązanych zadań.",
"delete": "Usuń powiązane zadanie", "delete": "Usuń powiązane zadanie",
"deleteText1": "Czy na pewno chcesz usunąć to powiązane zadanie?", "deleteText1": "Czy na pewno chcesz usunąć to powiązane zadanie?",
@ -848,19 +782,19 @@
"delete": { "delete": {
"header": "Usuń zespół", "header": "Usuń zespół",
"text1": "Czy na pewno chcesz usunąć ten zespół i wszystkich jego członków?", "text1": "Czy na pewno chcesz usunąć ten zespół i wszystkich jego członków?",
"text2": "All team members will lose access to projects and namespaces shared with this team. This CANNOT BE UNDONE!", "text2": "All team members will lose access to projects shared with this team. This CANNOT BE UNDONE!",
"success": "Zespół został pomyślnie usunięty." "success": "Zespół został pomyślnie usunięty."
}, },
"deleteUser": { "deleteUser": {
"header": "Usuń użytkownika z zespołu", "header": "Usuń użytkownika z zespołu",
"text1": "Czy na pewno chcesz usunąć tego użytkownika z zespołu?", "text1": "Czy na pewno chcesz usunąć tego użytkownika z zespołu?",
"text2": "They will lose access to all projects and namespaces this team has access to. This CANNOT BE UNDONE!", "text2": "They will lose access to all projects this team has access to. This CANNOT BE UNDONE!",
"success": "Użytkownik został pomyślnie usunięty z zespołu." "success": "Użytkownik został pomyślnie usunięty z zespołu."
}, },
"leave": { "leave": {
"title": "Leave team", "title": "Leave team",
"text1": "Are you sure you want to leave this team?", "text1": "Are you sure you want to leave this team?",
"text2": "You will lose access to all projects and namespaces this team has access to. If you change your mind you'll need a team admin to add you again.", "text2": "You will lose access to all projects this team has access to. If you change your mind you'll need a team admin to add you again.",
"success": "You have successfully left the team." "success": "You have successfully left the team."
} }
}, },
@ -894,7 +828,10 @@
"color": "Zmień kolor tego zadania", "color": "Zmień kolor tego zadania",
"move": "Move this task to another project", "move": "Move this task to another project",
"reminder": "Zarządzaj przypomnieniami o tym zadaniu", "reminder": "Zarządzaj przypomnieniami o tym zadaniu",
"description": "Toggle editing of the task description" "description": "Toggle editing of the task description",
"delete": "Delete this task",
"priority": "Change the priority of this task",
"favorite": "Mark this task as favorite / unfavorite"
}, },
"project": { "project": {
"title": "Project Views", "title": "Project Views",
@ -907,9 +844,9 @@
"title": "Nawigacja", "title": "Nawigacja",
"overview": "Przejdź do przeglądu", "overview": "Przejdź do przeglądu",
"upcoming": "Przejdź do nadchodzących zadań", "upcoming": "Przejdź do nadchodzących zadań",
"namespaces": "Navigate to namespaces & projects",
"labels": "Przejdź do etykiet", "labels": "Przejdź do etykiet",
"teams": "Przejdź do zespołów" "teams": "Przejdź do zespołów",
"projects": "Navigate to projects"
} }
}, },
"update": { "update": {
@ -924,7 +861,8 @@
"unarchive": "Cofnij archiwizację", "unarchive": "Cofnij archiwizację",
"setBackground": "Ustaw tło", "setBackground": "Ustaw tło",
"share": "Udostępnij", "share": "Udostępnij",
"newProject": "New project" "newProject": "New project",
"createProject": "Create project"
}, },
"apiConfig": { "apiConfig": {
"url": "URL Vikunji", "url": "URL Vikunji",
@ -943,7 +881,7 @@
"notification": { "notification": {
"title": "Powiadomienia", "title": "Powiadomienia",
"none": "Nie masz żadnych powiadomień. Miłego dnia!", "none": "Nie masz żadnych powiadomień. Miłego dnia!",
"explainer": "Notifications will appear here when actions on namespaces, projects or tasks you subscribed to happen." "explainer": "Notifications will appear here when actions projects or tasks you subscribed to happen."
}, },
"quickActions": { "quickActions": {
"commands": "Polecenia", "commands": "Polecenia",
@ -954,14 +892,12 @@
"teams": "Zespoły", "teams": "Zespoły",
"newProject": "Enter the title of the new project…", "newProject": "Enter the title of the new project…",
"newTask": "Wpisz tytuł nowego zadania…", "newTask": "Wpisz tytuł nowego zadania…",
"newNamespace": "Wpisz tytuł nowej sekcji…",
"newTeam": "Wpisz nazwę nowego zespołu…", "newTeam": "Wpisz nazwę nowego zespołu…",
"createTask": "Create a task in the current project ({title})", "createTask": "Create a task in the current project ({title})",
"createProject": "Create a project in the current namespace ({title})", "createProject": "Create a project",
"cmds": { "cmds": {
"newTask": "Nowe zadanie", "newTask": "Nowe zadanie",
"newProject": "New project", "newProject": "New project",
"newNamespace": "Nowa sekcja",
"newTeam": "Nowy zespół" "newTeam": "Nowy zespół"
} }
}, },
@ -1017,16 +953,9 @@
"4017": "Nieprawidłowe porównanie filtra zadań.", "4017": "Nieprawidłowe porównanie filtra zadań.",
"4018": "Nieprawidłowe połączenie filtra zadań.", "4018": "Nieprawidłowe połączenie filtra zadań.",
"4019": "Nieprawidłowa wartość filtra zadań.", "4019": "Nieprawidłowa wartość filtra zadań.",
"5001": "Sekcja nie istnieje.",
"5003": "Nie masz dostępu do określonej sekcji.",
"5006": "Nazwa sekcji nie może być pusta.",
"5009": "Aby wykonać tę akcję, musisz mieć uprawnienia do odczytu sekcji.",
"5010": "Ten zespół nie ma dostępu do tej sekcji.",
"5011": "Ten użytkownik ma już dostęp do tej sekcji.",
"5012": "Sekcja jest zarchiwizowana, dlatego może być dostępna tylko do odczytu.",
"6001": "Nazwa zespołu nie może być pusta.", "6001": "Nazwa zespołu nie może być pusta.",
"6002": "Zespół nie istnieje.", "6002": "Zespół nie istnieje.",
"6004": "The team already has access to that namespace or project.", "6004": "The team already has access to that project.",
"6005": "Użytkownik jest już członkiem tego zespołu.", "6005": "Użytkownik jest już członkiem tego zespołu.",
"6006": "Nie można usunąć ostatniego członka zespołu.", "6006": "Nie można usunąć ostatniego członka zespołu.",
"6007": "The team does not have access to the project to perform that action.", "6007": "The team does not have access to the project to perform that action.",
@ -1053,4 +982,4 @@
"frontendVersion": "Wersja frontendu: {version}", "frontendVersion": "Wersja frontendu: {version}",
"apiVersion": "Wersja API: {version}" "apiVersion": "Wersja API: {version}"
} }
} }

View File

@ -6,9 +6,7 @@
"welcomeEvening": "Boa noite, {username}!", "welcomeEvening": "Boa noite, {username}!",
"lastViewed": "Visto por último", "lastViewed": "Visto por último",
"project": { "project": {
"newText": "You can create a new project for your new tasks:", "importText": "Import your projects and tasks from other services into Vikunja:",
"new": "New project",
"importText": "Or import your projects and tasks from other services into Vikunja:",
"import": "Import your data into Vikunja" "import": "Import your data into Vikunja"
} }
}, },
@ -143,7 +141,7 @@
}, },
"deletion": { "deletion": {
"title": "Delete your Vikunja Account", "title": "Delete your Vikunja Account",
"text1": "The deletion of your account is permanent and cannot be undone. We will delete all your namespaces, projects, tasks and everything associated with it.", "text1": "The deletion of your account is permanent and cannot be undone. We will delete all your projects, tasks and everything associated with it.",
"text2": "To proceed, please enter your password. You will receive an email with further instructions.", "text2": "To proceed, please enter your password. You will receive an email with further instructions.",
"confirm": "Delete my account", "confirm": "Delete my account",
"requestSuccess": "The request was successful. You'll receive an email with further instructions.", "requestSuccess": "The request was successful. You'll receive an email with further instructions.",
@ -157,7 +155,7 @@
}, },
"export": { "export": {
"title": "Export your Vikunja data", "title": "Export your Vikunja data",
"description": "You can request a copy of all your Vikunja data. This include Namespaces, Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.", "description": "You can request a copy of all your Vikunja data. This includes Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
"descriptionPasswordRequired": "Please enter your password to proceed:", "descriptionPasswordRequired": "Please enter your password to proceed:",
"request": "Request a copy of my Vikunja Data", "request": "Request a copy of my Vikunja Data",
"success": "You've successfully requested your Vikunja Data! We will send you an email once it's ready to download.", "success": "You've successfully requested your Vikunja Data! We will send you an email once it's ready to download.",
@ -165,14 +163,18 @@
} }
}, },
"project": { "project": {
"archived": "This project is archived. It is not possible to create new or edit tasks for it.", "archivedMessage": "This project is archived. It is not possible to create new or edit tasks for it.",
"archived": "Archived",
"showArchived": "Show Archived",
"title": "Project Title", "title": "Project Title",
"color": "Color", "color": "Color",
"projects": "Projects", "projects": "Projects",
"parent": "Parent Project",
"search": "Type to search for a project…", "search": "Type to search for a project…",
"searchSelect": "Click or press enter to select this project", "searchSelect": "Click or press enter to select this project",
"shared": "Shared Projects", "shared": "Shared Projects",
"noDescriptionAvailable": "No project description is available.", "noDescriptionAvailable": "No project description is available.",
"inboxTitle": "Inbox",
"create": { "create": {
"header": "New project", "header": "New project",
"titlePlaceholder": "The project's title goes here…", "titlePlaceholder": "The project's title goes here…",
@ -210,7 +212,7 @@
"duplicate": { "duplicate": {
"title": "Duplicate this project", "title": "Duplicate this project",
"label": "Duplicate", "label": "Duplicate",
"text": "Select a namespace which should hold the duplicated project:", "text": "Select a parent project which should hold the duplicated project:",
"success": "The project was successfully duplicated." "success": "The project was successfully duplicated."
}, },
"edit": { "edit": {
@ -321,67 +323,6 @@
} }
} }
}, },
"namespace": {
"title": "Namespaces & Projects",
"namespace": "Namespace",
"showArchived": "Show Archived",
"noneAvailable": "Você não tem nenhum namespace no momento.",
"unarchive": "Desarquivar",
"archived": "Arquivado",
"noProjects": "This namespace does not contain any projects.",
"createProject": "Create a new project in this namespace.",
"namespaces": "Namespaces",
"search": "Digite para procurar por um namespace…",
"create": {
"title": "Novo namespace",
"titleRequired": "Por favor, especifique um título.",
"explanation": "A namespace is a collection of projects you can share and use to organize your projects with. In fact, every project belongs to a namespace.",
"tooltip": "O que é um namespace?",
"success": "O namespace foi criado com sucesso."
},
"archive": {
"titleArchive": "Arquivar \"{namespace}\"",
"titleUnarchive": "Desarquivar \"{namespace}\"",
"archiveText": "You won't be able to edit this namespace or create new projects until you un-archive it. This will also archive all projects in this namespace.",
"unarchiveText": "You will be able to create new projects or edit it.",
"success": "O namespace foi arquivado com sucesso.",
"unarchiveSuccess": "O namespace foi desarquivado com sucesso.",
"description": "If a namespace is archived, you cannot create new projects or edit it."
},
"delete": {
"title": "Excluir \"{namespace}\"",
"text1": "Are you sure you want to delete this namespace and all of its contents?",
"text2": "This includes all projects and tasks and CANNOT BE UNDONE!",
"success": "O namespace foi excluído com sucesso."
},
"edit": {
"title": "Editar \"{namespace}\"",
"success": "O namespace foi atualizado com sucesso."
},
"share": {
"title": "Compartilhar \"{namespace}\""
},
"attributes": {
"title": "Título do Namespace",
"titlePlaceholder": "O título do namespace fica aqui…",
"description": "Descrição",
"descriptionPlaceholder": "A descrição do namespace fica aqui…",
"color": "Cor",
"archived": "Está arquivado",
"isArchived": "Este namespace está arquivado"
},
"pseudo": {
"sharedProjects": {
"title": "Shared Projects"
},
"favorites": {
"title": "Favoritos"
},
"savedFilters": {
"title": "Filtros"
}
}
},
"filters": { "filters": {
"title": "Filtros", "title": "Filtros",
"clear": "Limpar Filtros", "clear": "Limpar Filtros",
@ -403,7 +344,7 @@
}, },
"create": { "create": {
"title": "Novo filtro salvo", "title": "Novo filtro salvo",
"description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed. Once created, it will appear in a special namespace.", "description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed.",
"action": "Create new saved filter", "action": "Create new saved filter",
"titleRequired": "Please provide a title for the filter." "titleRequired": "Please provide a title for the filter."
}, },
@ -674,19 +615,13 @@
"updated": "Atualizado" "updated": "Atualizado"
}, },
"subscription": { "subscription": {
"subscribedProjectThroughParentNamespace": "You can't unsubscribe here because you are subscribed to this project through its namespace.",
"subscribedTaskThroughParentNamespace": "You can't unsubscribe here because you are subscribed to this task through its namespace.",
"subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.", "subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.",
"subscribedNamespace": "You are currently subscribed to this namespace and will receive notifications for changes.",
"notSubscribedNamespace": "You are not subscribed to this namespace and won't receive notifications for changes.",
"subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.", "subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.",
"notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.", "notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.",
"subscribedTask": "You are currently subscribed to this task and will receive notifications for changes.", "subscribedTask": "You are currently subscribed to this task and will receive notifications for changes.",
"notSubscribedTask": "You are not subscribed to this task and won't receive notifications for changes.", "notSubscribedTask": "You are not subscribed to this task and won't receive notifications for changes.",
"subscribe": "Inscrever-se", "subscribe": "Inscrever-se",
"unsubscribe": "Desinscrever-se", "unsubscribe": "Desinscrever-se",
"subscribeSuccessNamespace": "You are now subscribed to this namespace",
"unsubscribeSuccessNamespace": "You are now unsubscribed to this namespace",
"subscribeSuccessProject": "You are now subscribed to this project", "subscribeSuccessProject": "You are now subscribed to this project",
"unsubscribeSuccessProject": "You are now unsubscribed to this project", "unsubscribeSuccessProject": "You are now unsubscribed to this project",
"subscribeSuccessTask": "You are now subscribed to this task", "subscribeSuccessTask": "You are now subscribed to this task",
@ -763,7 +698,6 @@
"searchPlaceholder": "Type search for a new task to add as related…", "searchPlaceholder": "Type search for a new task to add as related…",
"createPlaceholder": "Add this as new related task", "createPlaceholder": "Add this as new related task",
"differentProject": "This task belongs to a different project.", "differentProject": "This task belongs to a different project.",
"differentNamespace": "This task belongs to a different namespace.",
"noneYet": "No task relations yet.", "noneYet": "No task relations yet.",
"delete": "Delete Task Relation", "delete": "Delete Task Relation",
"deleteText1": "Are you sure you want to delete this task relation?", "deleteText1": "Are you sure you want to delete this task relation?",
@ -848,19 +782,19 @@
"delete": { "delete": {
"header": "Excluir a equipe", "header": "Excluir a equipe",
"text1": "Are you sure you want to delete this team and all of its members?", "text1": "Are you sure you want to delete this team and all of its members?",
"text2": "All team members will lose access to projects and namespaces shared with this team. This CANNOT BE UNDONE!", "text2": "All team members will lose access to projects shared with this team. This CANNOT BE UNDONE!",
"success": "A equipe foi excluída com sucesso." "success": "A equipe foi excluída com sucesso."
}, },
"deleteUser": { "deleteUser": {
"header": "Remove a user from the team", "header": "Remove a user from the team",
"text1": "Are you sure you want to remove this user from the team?", "text1": "Are you sure you want to remove this user from the team?",
"text2": "They will lose access to all projects and namespaces this team has access to. This CANNOT BE UNDONE!", "text2": "They will lose access to all projects this team has access to. This CANNOT BE UNDONE!",
"success": "O usuário foi removido da equipe com sucesso." "success": "O usuário foi removido da equipe com sucesso."
}, },
"leave": { "leave": {
"title": "Leave team", "title": "Leave team",
"text1": "Are you sure you want to leave this team?", "text1": "Are you sure you want to leave this team?",
"text2": "You will lose access to all projects and namespaces this team has access to. If you change your mind you'll need a team admin to add you again.", "text2": "You will lose access to all projects this team has access to. If you change your mind you'll need a team admin to add you again.",
"success": "You have successfully left the team." "success": "You have successfully left the team."
} }
}, },
@ -894,7 +828,10 @@
"color": "Change the color of this task", "color": "Change the color of this task",
"move": "Move this task to another project", "move": "Move this task to another project",
"reminder": "Manage reminders of this task", "reminder": "Manage reminders of this task",
"description": "Toggle editing of the task description" "description": "Toggle editing of the task description",
"delete": "Delete this task",
"priority": "Change the priority of this task",
"favorite": "Mark this task as favorite / unfavorite"
}, },
"project": { "project": {
"title": "Project Views", "title": "Project Views",
@ -907,9 +844,9 @@
"title": "Navigation", "title": "Navigation",
"overview": "Navigate to overview", "overview": "Navigate to overview",
"upcoming": "Navigate to upcoming tasks", "upcoming": "Navigate to upcoming tasks",
"namespaces": "Navigate to namespaces & projects",
"labels": "Navigate to labels", "labels": "Navigate to labels",
"teams": "Navigate to teams" "teams": "Navigate to teams",
"projects": "Navigate to projects"
} }
}, },
"update": { "update": {
@ -924,7 +861,8 @@
"unarchive": "Un-Archive", "unarchive": "Un-Archive",
"setBackground": "Set background", "setBackground": "Set background",
"share": "Share", "share": "Share",
"newProject": "New project" "newProject": "New project",
"createProject": "Create project"
}, },
"apiConfig": { "apiConfig": {
"url": "Vikunja URL", "url": "Vikunja URL",
@ -943,7 +881,7 @@
"notification": { "notification": {
"title": "Notificações", "title": "Notificações",
"none": "You don't have any notifications. Have a nice day!", "none": "You don't have any notifications. Have a nice day!",
"explainer": "Notifications will appear here when actions on namespaces, projects or tasks you subscribed to happen." "explainer": "Notifications will appear here when actions projects or tasks you subscribed to happen."
}, },
"quickActions": { "quickActions": {
"commands": "Comandos", "commands": "Comandos",
@ -954,14 +892,12 @@
"teams": "Equipes", "teams": "Equipes",
"newProject": "Enter the title of the new project…", "newProject": "Enter the title of the new project…",
"newTask": "Enter the title of the new task…", "newTask": "Enter the title of the new task…",
"newNamespace": "Enter the title of the new namespace…",
"newTeam": "Enter the name of the new team…", "newTeam": "Enter the name of the new team…",
"createTask": "Create a task in the current project ({title})", "createTask": "Create a task in the current project ({title})",
"createProject": "Create a project in the current namespace ({title})", "createProject": "Create a project",
"cmds": { "cmds": {
"newTask": "Nova tarefa", "newTask": "Nova tarefa",
"newProject": "New project", "newProject": "New project",
"newNamespace": "Novo namespace",
"newTeam": "Nova equipe" "newTeam": "Nova equipe"
} }
}, },
@ -1017,16 +953,9 @@
"4017": "Invalid task filter comparator.", "4017": "Invalid task filter comparator.",
"4018": "Invalid task filter concatenator.", "4018": "Invalid task filter concatenator.",
"4019": "Invalid task filter value.", "4019": "Invalid task filter value.",
"5001": "The namespace does not exist.",
"5003": "You do not have access to the specified namespace.",
"5006": "The namespace name cannot be empty.",
"5009": "You need to have namespace read access to perform that action.",
"5010": "This team does not have access to that namespace.",
"5011": "This user has already access to that namespace.",
"5012": "The namespace is archived and can therefore only be accessed read only.",
"6001": "The team name cannot be empty.", "6001": "The team name cannot be empty.",
"6002": "The team does not exist.", "6002": "The team does not exist.",
"6004": "The team already has access to that namespace or project.", "6004": "The team already has access to that project.",
"6005": "The user is already a member of that team.", "6005": "The user is already a member of that team.",
"6006": "Cannot delete the last team member.", "6006": "Cannot delete the last team member.",
"6007": "The team does not have access to the project to perform that action.", "6007": "The team does not have access to the project to perform that action.",
@ -1053,4 +982,4 @@
"frontendVersion": "Frontend Version: {version}", "frontendVersion": "Frontend Version: {version}",
"apiVersion": "API Version: {version}" "apiVersion": "API Version: {version}"
} }
} }

View File

@ -6,9 +6,7 @@
"welcomeEvening": "Boa Tarde {username}!", "welcomeEvening": "Boa Tarde {username}!",
"lastViewed": "Visto recentemente", "lastViewed": "Visto recentemente",
"project": { "project": {
"newText": "Podes criar um novo projeto para as tuas novas tarefas:", "importText": "Import your projects and tasks from other services into Vikunja:",
"new": "Novo projeto",
"importText": "Ou importar os teus projetos e tarefas de outros serviços para o Vikunja:",
"import": "Importar os teus dados para o Vikunja" "import": "Importar os teus dados para o Vikunja"
} }
}, },
@ -143,7 +141,7 @@
}, },
"deletion": { "deletion": {
"title": "Eliminar a tua conta Vikunja", "title": "Eliminar a tua conta Vikunja",
"text1": "A eliminação da tua conta é permanente e não pode ser revertida. Vão ser eliminados todos os teus espaços, projetos, tarefas e tudo o que lhes está associado.", "text1": "The deletion of your account is permanent and cannot be undone. We will delete all your projects, tasks and everything associated with it.",
"text2": "Para prosseguires, introduz por favor a tua palavra-passe. Receberás um e-mail com mais instruções.", "text2": "Para prosseguires, introduz por favor a tua palavra-passe. Receberás um e-mail com mais instruções.",
"confirm": "Eliminar a minha conta", "confirm": "Eliminar a minha conta",
"requestSuccess": "A solicitação foi bem sucedida. Receberás um e-mail com mais instruções.", "requestSuccess": "A solicitação foi bem sucedida. Receberás um e-mail com mais instruções.",
@ -157,7 +155,7 @@
}, },
"export": { "export": {
"title": "Exportar os teus dados do Vikunja", "title": "Exportar os teus dados do Vikunja",
"description": "Podes solicitar uma cópia de todos os teus dados do Vikunja. Isso inclui Espaços, Projetos, Tarefas e tudo o que lhes está associado. Podes importar esses dados em qualquer instância do Vikunja através da função de migração.", "description": "You can request a copy of all your Vikunja data. This includes Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
"descriptionPasswordRequired": "Por favor, introduz a tua palavra-passe para continuar:", "descriptionPasswordRequired": "Por favor, introduz a tua palavra-passe para continuar:",
"request": "Solicitar uma cópia dos meus dados do Vikunja", "request": "Solicitar uma cópia dos meus dados do Vikunja",
"success": "Solicitaste com sucesso os teus dados do Vikunja! Enviaremos um e-mail assim que estiverem prontos para download.", "success": "Solicitaste com sucesso os teus dados do Vikunja! Enviaremos um e-mail assim que estiverem prontos para download.",
@ -165,14 +163,18 @@
} }
}, },
"project": { "project": {
"archived": "Este projeto está arquivado. Não é possível editar ou criar novas tarefas para ele.", "archivedMessage": "This project is archived. It is not possible to create new or edit tasks for it.",
"archived": "Archived",
"showArchived": "Show Archived",
"title": "Título do Projeto", "title": "Título do Projeto",
"color": "Cor", "color": "Cor",
"projects": "Projetos", "projects": "Projetos",
"parent": "Parent Project",
"search": "Escreve para pesquisar por um projeto…", "search": "Escreve para pesquisar por um projeto…",
"searchSelect": "Clica ou pressiona Enter para selecionar este projeto", "searchSelect": "Clica ou pressiona Enter para selecionar este projeto",
"shared": "Projetos Partilhados", "shared": "Projetos Partilhados",
"noDescriptionAvailable": "Não está disponível nenhuma descrição do projeto.", "noDescriptionAvailable": "Não está disponível nenhuma descrição do projeto.",
"inboxTitle": "Inbox",
"create": { "create": {
"header": "Novo projeto", "header": "Novo projeto",
"titlePlaceholder": "O título do projeto será aqui…", "titlePlaceholder": "O título do projeto será aqui…",
@ -210,7 +212,7 @@
"duplicate": { "duplicate": {
"title": "Duplicar este projeto", "title": "Duplicar este projeto",
"label": "Duplicar", "label": "Duplicar",
"text": "Selecione um espaço para colocar o projeto duplicado:", "text": "Select a parent project which should hold the duplicated project:",
"success": "O projeto foi duplicado com sucesso." "success": "O projeto foi duplicado com sucesso."
}, },
"edit": { "edit": {
@ -321,67 +323,6 @@
} }
} }
}, },
"namespace": {
"title": "Espaços e Projetos",
"namespace": "Espaço",
"showArchived": "Mostrar Arquivados",
"noneAvailable": "Por enquanto não tens nenhum espaço.",
"unarchive": "Desarquivar",
"archived": "Arquivado",
"noProjects": "Este espaço não contém qualquer projeto.",
"createProject": "Criar uma novo projeto neste espaço.",
"namespaces": "Espaços",
"search": "Escreva para pesquisar por um espaço…",
"create": {
"title": "Novo espaço",
"titleRequired": "Por favor, especifica um título.",
"explanation": "Um espaço é uma coleção de projetos que podes partilhar e utilizar para organizar as tuas listas. De facto, cada projeto pertence a um espaço.",
"tooltip": "O que é um espaço?",
"success": "O espaço foi criado com sucesso."
},
"archive": {
"titleArchive": "Arquivar \"{namespace}\"",
"titleUnarchive": "Desarquivar \"{namespace}\"",
"archiveText": "Não será possível editar este espaço nem criar novos projetos enquanto não o desarquivares. Isto também irá arquivar todas os projetos existentes neste espaço.",
"unarchiveText": "Poderás criar novos projetos ou editá-los.",
"success": "O espaço foi arquivado com sucesso.",
"unarchiveSuccess": "O espaço foi desarquivado com sucesso.",
"description": "Se um espaço estiver arquivado, não poderás criar novos projetos ou editá-los."
},
"delete": {
"title": "Eliminar \"{namespace}\"",
"text1": "Tens a certeza que pretendes eliminar este espaço e todo o seu conteúdo?",
"text2": "Isto inclui todas os projetos e tarefas, e NÃO PODE SER REVERTIDO!",
"success": "O espaço foi eliminado com sucesso."
},
"edit": {
"title": "Editar \"{namespace}\"",
"success": "O espaço foi atualizado com sucesso."
},
"share": {
"title": "Partilhar \"{namespace}\""
},
"attributes": {
"title": "Título do Espaço",
"titlePlaceholder": "O título do espaço será aqui…",
"description": "Descrição",
"descriptionPlaceholder": "A descrição do espaço será aqui…",
"color": "Cor",
"archived": "Arquivado",
"isArchived": "O espaço está arquivado"
},
"pseudo": {
"sharedProjects": {
"title": "Projetos Partilhados"
},
"favorites": {
"title": "Favoritos"
},
"savedFilters": {
"title": "Filtros"
}
}
},
"filters": { "filters": {
"title": "Filtros", "title": "Filtros",
"clear": "Limpar Filtros", "clear": "Limpar Filtros",
@ -403,7 +344,7 @@
}, },
"create": { "create": {
"title": "Novo Filtro Memorizado", "title": "Novo Filtro Memorizado",
"description": "Um filtro memorizado é uma lista virtual que é compilada a partir de um conjunto de filtros de cada vez que é acedido. Uma vez criado, irá aparecer num espaço especial.", "description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed.",
"action": "Criar novo filtro memorizado", "action": "Criar novo filtro memorizado",
"titleRequired": "Por favor, insere um título para o filtro." "titleRequired": "Por favor, insere um título para o filtro."
}, },
@ -674,19 +615,13 @@
"updated": "Atualizado" "updated": "Atualizado"
}, },
"subscription": { "subscription": {
"subscribedProjectThroughParentNamespace": "Não podes cancelar a tua subscrição aqui porque estás subscrito neste projeto através do seu espaço.",
"subscribedTaskThroughParentNamespace": "Não podes cancelar a tua subscrição aqui porque estás subscrito nesta tarefa através do seu espaço.",
"subscribedTaskThroughParentProject": "Não podes cancelar a tua subscrição aqui porque estás subscrito nesta tarefa através do seu projeto.", "subscribedTaskThroughParentProject": "Não podes cancelar a tua subscrição aqui porque estás subscrito nesta tarefa através do seu projeto.",
"subscribedNamespace": "Estás atualmente subscrito a este espaço e serás notificado de alterações.",
"notSubscribedNamespace": "Não estás subscrito a este espaço e não serás notificado de alterações.",
"subscribedProject": "Estás atualmente subscrito a este projeto e serás notificado de alterações.", "subscribedProject": "Estás atualmente subscrito a este projeto e serás notificado de alterações.",
"notSubscribedProject": "Não estás subscrito a este projeto e não serás notificado de alterações.", "notSubscribedProject": "Não estás subscrito a este projeto e não serás notificado de alterações.",
"subscribedTask": "Estás atualmente subscrito a esta tarefa e serás notificado de alterações.", "subscribedTask": "Estás atualmente subscrito a esta tarefa e serás notificado de alterações.",
"notSubscribedTask": "Não estás subscrito a esta tarefa e não serás notificado de alterações.", "notSubscribedTask": "Não estás subscrito a esta tarefa e não serás notificado de alterações.",
"subscribe": "Subscrever", "subscribe": "Subscrever",
"unsubscribe": "Remover Subscrição", "unsubscribe": "Remover Subscrição",
"subscribeSuccessNamespace": "Estás agora subscrito a este espaço",
"unsubscribeSuccessNamespace": "Não estás mais subcrito a este espaço",
"subscribeSuccessProject": "Estás agora subscrito a este projeto", "subscribeSuccessProject": "Estás agora subscrito a este projeto",
"unsubscribeSuccessProject": "Não estás mais subcrito a este projeto", "unsubscribeSuccessProject": "Não estás mais subcrito a este projeto",
"subscribeSuccessTask": "Estás agora subscrito a esta tarefa", "subscribeSuccessTask": "Estás agora subscrito a esta tarefa",
@ -763,7 +698,6 @@
"searchPlaceholder": "Escreve para pesquisar uma tarefa a adicionar como relacionada…", "searchPlaceholder": "Escreve para pesquisar uma tarefa a adicionar como relacionada…",
"createPlaceholder": "Adicionar como nova tarefa relacionada", "createPlaceholder": "Adicionar como nova tarefa relacionada",
"differentProject": "Esta tarefa pertence a um projeto diferente.", "differentProject": "Esta tarefa pertence a um projeto diferente.",
"differentNamespace": "Esta tarefa pertence a um espaço diferente.",
"noneYet": "Ainda sem tarefas relacionadas.", "noneYet": "Ainda sem tarefas relacionadas.",
"delete": "Eliminar Relação Entre Tarefas", "delete": "Eliminar Relação Entre Tarefas",
"deleteText1": "Tens a certeza que pretendes eliminar esta relação entre tarefas?", "deleteText1": "Tens a certeza que pretendes eliminar esta relação entre tarefas?",
@ -848,19 +782,19 @@
"delete": { "delete": {
"header": "Eliminar equipa", "header": "Eliminar equipa",
"text1": "Tens a certeza que pretendes eliminar esta equipa e todos os seus membros?", "text1": "Tens a certeza que pretendes eliminar esta equipa e todos os seus membros?",
"text2": "Todos os membros da equipa perderão acesso aos projetos e espaços partilhados com esta equipa. Isto NÃO PODE SER REVERTIDO!", "text2": "All team members will lose access to projects shared with this team. This CANNOT BE UNDONE!",
"success": "A equipa foi eliminada com sucesso." "success": "A equipa foi eliminada com sucesso."
}, },
"deleteUser": { "deleteUser": {
"header": "Remover utilizador da equipa", "header": "Remover utilizador da equipa",
"text1": "Tens a certeza que pretendes remover este utilizador da equipa?", "text1": "Tens a certeza que pretendes remover este utilizador da equipa?",
"text2": "Eles perderão o acesso a todos os projetos e espaços a que esta equipa tem acesso. Isto NÃO PODER SER REVERTIDO!", "text2": "They will lose access to all projects this team has access to. This CANNOT BE UNDONE!",
"success": "O utilizador foi removido da equipa com sucesso." "success": "O utilizador foi removido da equipa com sucesso."
}, },
"leave": { "leave": {
"title": "Sair da equipa", "title": "Sair da equipa",
"text1": "Tens a certeza de que queres sair desta equipa?", "text1": "Tens a certeza de que queres sair desta equipa?",
"text2": "Vais perder o acesso a todos os projetos e espaços a que esta equipa tem acesso. Se mudares de ideias, vais necessitar que um administrador da equipa te adicione novamente.", "text2": "You will lose access to all projects this team has access to. If you change your mind you'll need a team admin to add you again.",
"success": "Saíste da equipa com sucesso." "success": "Saíste da equipa com sucesso."
} }
}, },
@ -894,7 +828,10 @@
"color": "Alterar a cor desta tarefa", "color": "Alterar a cor desta tarefa",
"move": "Mover esta tarefa para outro projeto", "move": "Mover esta tarefa para outro projeto",
"reminder": "Gerir lembretes desta tarefa", "reminder": "Gerir lembretes desta tarefa",
"description": "Alternar edição da descrição da tarefa" "description": "Alternar edição da descrição da tarefa",
"delete": "Eliminar esta tarefa",
"priority": "Alterar a prioridade desta tarefa",
"favorite": "Marcar / Desmarcar esta tarefa como favorita"
}, },
"project": { "project": {
"title": "Vista do Projeto", "title": "Vista do Projeto",
@ -907,9 +844,9 @@
"title": "Navegação", "title": "Navegação",
"overview": "Ir para a vista geral", "overview": "Ir para a vista geral",
"upcoming": "Ir para próximas tarefas", "upcoming": "Ir para próximas tarefas",
"namespaces": "Ir para espaços e projetos",
"labels": "Navegar para etiquetas", "labels": "Navegar para etiquetas",
"teams": "Navegar para equipas" "teams": "Navegar para equipas",
"projects": "Navigate to projects"
} }
}, },
"update": { "update": {
@ -924,7 +861,8 @@
"unarchive": "Desarquivar", "unarchive": "Desarquivar",
"setBackground": "Definir Fundo", "setBackground": "Definir Fundo",
"share": "Partilhar", "share": "Partilhar",
"newProject": "Novo projeto" "newProject": "Novo projeto",
"createProject": "Create project"
}, },
"apiConfig": { "apiConfig": {
"url": "URL do Vikunja", "url": "URL do Vikunja",
@ -943,7 +881,7 @@
"notification": { "notification": {
"title": "Notificações", "title": "Notificações",
"none": "Não tens nenhuma notificação. Tem um bom dia!", "none": "Não tens nenhuma notificação. Tem um bom dia!",
"explainer": "As notificações aparecerão aqui quando ocorrem ações em espaços, projetos ou tarefas às quais estejas subscrito." "explainer": "Notifications will appear here when actions projects or tasks you subscribed to happen."
}, },
"quickActions": { "quickActions": {
"commands": "Comandos", "commands": "Comandos",
@ -954,14 +892,12 @@
"teams": "Equipas", "teams": "Equipas",
"newProject": "Insere o título do novo espaço…", "newProject": "Insere o título do novo espaço…",
"newTask": "Insere o título da nova tarefa…", "newTask": "Insere o título da nova tarefa…",
"newNamespace": "Insere o título do novo espaço…",
"newTeam": "Insere o nome da nova equipa…", "newTeam": "Insere o nome da nova equipa…",
"createTask": "Cria uma tarefa no projeto atual ({title})", "createTask": "Cria uma tarefa no projeto atual ({title})",
"createProject": "Cria um projeto no espaço atual ({title})", "createProject": "Create a project",
"cmds": { "cmds": {
"newTask": "Nova tarefa", "newTask": "Nova tarefa",
"newProject": "Novo projeto", "newProject": "Novo projeto",
"newNamespace": "Novo espaço",
"newTeam": "Nova equipa" "newTeam": "Nova equipa"
} }
}, },
@ -1017,16 +953,9 @@
"4017": "Filtro de comparação de tarefas inválido.", "4017": "Filtro de comparação de tarefas inválido.",
"4018": "Filtro de encademanto de tarefas inválido.", "4018": "Filtro de encademanto de tarefas inválido.",
"4019": "Valor de filtro de tarefas inválido.", "4019": "Valor de filtro de tarefas inválido.",
"5001": "O espaço não existe.",
"5003": "Não tens acesso ao espaço especificado.",
"5006": "O nome do espaço não pode estar vazio.",
"5009": "Precisas ter permissão de leitura deste espaço para executar essa ação.",
"5010": "Esta equipa não tem acesso a esse espaço.",
"5011": "Este utilizador já tem acesso a esse espaço.",
"5012": "O espaço está arquivado, portanto, só pode ser acedido para leitura.",
"6001": "O nome da equipa não pode estar vazio.", "6001": "O nome da equipa não pode estar vazio.",
"6002": "A equipa não existe.", "6002": "A equipa não existe.",
"6004": "A equipa tem já acesso a esse espaço ou projeto.", "6004": "The team already has access to that project.",
"6005": "O utilizador é já membro dessa equipa.", "6005": "O utilizador é já membro dessa equipa.",
"6006": "Não podes eliminar o último membro da equipa.", "6006": "Não podes eliminar o último membro da equipa.",
"6007": "A equipa não tem acesso ao projeto para executar essa ação.", "6007": "A equipa não tem acesso ao projeto para executar essa ação.",
@ -1053,4 +982,4 @@
"frontendVersion": "Versão Atual: {version}", "frontendVersion": "Versão Atual: {version}",
"apiVersion": "Versão da API: {version}" "apiVersion": "Versão da API: {version}"
} }
} }

View File

@ -6,9 +6,7 @@
"welcomeEvening": "Good Evening {username}!", "welcomeEvening": "Good Evening {username}!",
"lastViewed": "Last viewed", "lastViewed": "Last viewed",
"project": { "project": {
"newText": "You can create a new project for your new tasks:", "importText": "Import your projects and tasks from other services into Vikunja:",
"new": "New project",
"importText": "Or import your projects and tasks from other services into Vikunja:",
"import": "Import your data into Vikunja" "import": "Import your data into Vikunja"
} }
}, },
@ -143,7 +141,7 @@
}, },
"deletion": { "deletion": {
"title": "Delete your Vikunja Account", "title": "Delete your Vikunja Account",
"text1": "The deletion of your account is permanent and cannot be undone. We will delete all your namespaces, projects, tasks and everything associated with it.", "text1": "The deletion of your account is permanent and cannot be undone. We will delete all your projects, tasks and everything associated with it.",
"text2": "To proceed, please enter your password. You will receive an email with further instructions.", "text2": "To proceed, please enter your password. You will receive an email with further instructions.",
"confirm": "Delete my account", "confirm": "Delete my account",
"requestSuccess": "The request was successful. You'll receive an email with further instructions.", "requestSuccess": "The request was successful. You'll receive an email with further instructions.",
@ -157,7 +155,7 @@
}, },
"export": { "export": {
"title": "Export your Vikunja data", "title": "Export your Vikunja data",
"description": "You can request a copy of all your Vikunja data. This include Namespaces, Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.", "description": "You can request a copy of all your Vikunja data. This includes Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
"descriptionPasswordRequired": "Please enter your password to proceed:", "descriptionPasswordRequired": "Please enter your password to proceed:",
"request": "Request a copy of my Vikunja Data", "request": "Request a copy of my Vikunja Data",
"success": "You've successfully requested your Vikunja Data! We will send you an email once it's ready to download.", "success": "You've successfully requested your Vikunja Data! We will send you an email once it's ready to download.",
@ -165,14 +163,18 @@
} }
}, },
"project": { "project": {
"archived": "This project is archived. It is not possible to create new or edit tasks for it.", "archivedMessage": "This project is archived. It is not possible to create new or edit tasks for it.",
"archived": "Archived",
"showArchived": "Show Archived",
"title": "Project Title", "title": "Project Title",
"color": "Color", "color": "Color",
"projects": "Projects", "projects": "Projects",
"parent": "Parent Project",
"search": "Type to search for a project…", "search": "Type to search for a project…",
"searchSelect": "Click or press enter to select this project", "searchSelect": "Click or press enter to select this project",
"shared": "Shared Projects", "shared": "Shared Projects",
"noDescriptionAvailable": "No project description is available.", "noDescriptionAvailable": "No project description is available.",
"inboxTitle": "Inbox",
"create": { "create": {
"header": "New project", "header": "New project",
"titlePlaceholder": "The project's title goes here…", "titlePlaceholder": "The project's title goes here…",
@ -210,7 +212,7 @@
"duplicate": { "duplicate": {
"title": "Duplicate this project", "title": "Duplicate this project",
"label": "Duplicate", "label": "Duplicate",
"text": "Select a namespace which should hold the duplicated project:", "text": "Select a parent project which should hold the duplicated project:",
"success": "The project was successfully duplicated." "success": "The project was successfully duplicated."
}, },
"edit": { "edit": {
@ -321,67 +323,6 @@
} }
} }
}, },
"namespace": {
"title": "Namespaces & Projects",
"namespace": "Namespace",
"showArchived": "Show Archived",
"noneAvailable": "You don't have any namespaces right now.",
"unarchive": "Un-Archive",
"archived": "Archived",
"noProjects": "This namespace does not contain any projects.",
"createProject": "Create a new project in this namespace.",
"namespaces": "Namespaces",
"search": "Type to search for a namespace…",
"create": {
"title": "New namespace",
"titleRequired": "Please specify a title.",
"explanation": "A namespace is a collection of projects you can share and use to organize your projects with. In fact, every project belongs to a namespace.",
"tooltip": "What's a namespace?",
"success": "The namespace was successfully created."
},
"archive": {
"titleArchive": "Archive \"{namespace}\"",
"titleUnarchive": "Un-Archive \"{namespace}\"",
"archiveText": "You won't be able to edit this namespace or create new projects until you un-archive it. This will also archive all projects in this namespace.",
"unarchiveText": "You will be able to create new projects or edit it.",
"success": "The namespace was successfully archived.",
"unarchiveSuccess": "The namespace was successfully un-archived.",
"description": "If a namespace is archived, you cannot create new projects or edit it."
},
"delete": {
"title": "Delete \"{namespace}\"",
"text1": "Are you sure you want to delete this namespace and all of its contents?",
"text2": "This includes all projects and tasks and CANNOT BE UNDONE!",
"success": "The namespace was successfully deleted."
},
"edit": {
"title": "Edit \"{namespace}\"",
"success": "The namespace was successfully updated."
},
"share": {
"title": "Share \"{namespace}\""
},
"attributes": {
"title": "Namespace Title",
"titlePlaceholder": "The namespace title goes here…",
"description": "Description",
"descriptionPlaceholder": "The namespaces description goes here…",
"color": "Color",
"archived": "Is Archived",
"isArchived": "This namespace is archived"
},
"pseudo": {
"sharedProjects": {
"title": "Shared Projects"
},
"favorites": {
"title": "Favorites"
},
"savedFilters": {
"title": "Filters"
}
}
},
"filters": { "filters": {
"title": "Filters", "title": "Filters",
"clear": "Clear Filters", "clear": "Clear Filters",
@ -403,7 +344,7 @@
}, },
"create": { "create": {
"title": "New Saved Filter", "title": "New Saved Filter",
"description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed. Once created, it will appear in a special namespace.", "description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed.",
"action": "Create new saved filter", "action": "Create new saved filter",
"titleRequired": "Please provide a title for the filter." "titleRequired": "Please provide a title for the filter."
}, },
@ -674,19 +615,13 @@
"updated": "Updated" "updated": "Updated"
}, },
"subscription": { "subscription": {
"subscribedProjectThroughParentNamespace": "You can't unsubscribe here because you are subscribed to this project through its namespace.",
"subscribedTaskThroughParentNamespace": "You can't unsubscribe here because you are subscribed to this task through its namespace.",
"subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.", "subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.",
"subscribedNamespace": "You are currently subscribed to this namespace and will receive notifications for changes.",
"notSubscribedNamespace": "You are not subscribed to this namespace and won't receive notifications for changes.",
"subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.", "subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.",
"notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.", "notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.",
"subscribedTask": "You are currently subscribed to this task and will receive notifications for changes.", "subscribedTask": "You are currently subscribed to this task and will receive notifications for changes.",
"notSubscribedTask": "You are not subscribed to this task and won't receive notifications for changes.", "notSubscribedTask": "You are not subscribed to this task and won't receive notifications for changes.",
"subscribe": "Subscribe", "subscribe": "Subscribe",
"unsubscribe": "Unsubscribe", "unsubscribe": "Unsubscribe",
"subscribeSuccessNamespace": "You are now subscribed to this namespace",
"unsubscribeSuccessNamespace": "You are now unsubscribed to this namespace",
"subscribeSuccessProject": "You are now subscribed to this project", "subscribeSuccessProject": "You are now subscribed to this project",
"unsubscribeSuccessProject": "You are now unsubscribed to this project", "unsubscribeSuccessProject": "You are now unsubscribed to this project",
"subscribeSuccessTask": "You are now subscribed to this task", "subscribeSuccessTask": "You are now subscribed to this task",
@ -763,7 +698,6 @@
"searchPlaceholder": "Type search for a new task to add as related…", "searchPlaceholder": "Type search for a new task to add as related…",
"createPlaceholder": "Add this as new related task", "createPlaceholder": "Add this as new related task",
"differentProject": "This task belongs to a different project.", "differentProject": "This task belongs to a different project.",
"differentNamespace": "This task belongs to a different namespace.",
"noneYet": "No task relations yet.", "noneYet": "No task relations yet.",
"delete": "Delete Task Relation", "delete": "Delete Task Relation",
"deleteText1": "Are you sure you want to delete this task relation?", "deleteText1": "Are you sure you want to delete this task relation?",
@ -848,19 +782,19 @@
"delete": { "delete": {
"header": "Delete the team", "header": "Delete the team",
"text1": "Are you sure you want to delete this team and all of its members?", "text1": "Are you sure you want to delete this team and all of its members?",
"text2": "All team members will lose access to projects and namespaces shared with this team. This CANNOT BE UNDONE!", "text2": "All team members will lose access to projects shared with this team. This CANNOT BE UNDONE!",
"success": "The team was successfully deleted." "success": "The team was successfully deleted."
}, },
"deleteUser": { "deleteUser": {
"header": "Remove a user from the team", "header": "Remove a user from the team",
"text1": "Are you sure you want to remove this user from the team?", "text1": "Are you sure you want to remove this user from the team?",
"text2": "They will lose access to all projects and namespaces this team has access to. This CANNOT BE UNDONE!", "text2": "They will lose access to all projects this team has access to. This CANNOT BE UNDONE!",
"success": "The user was successfully deleted from the team." "success": "The user was successfully deleted from the team."
}, },
"leave": { "leave": {
"title": "Leave team", "title": "Leave team",
"text1": "Are you sure you want to leave this team?", "text1": "Are you sure you want to leave this team?",
"text2": "You will lose access to all projects and namespaces this team has access to. If you change your mind you'll need a team admin to add you again.", "text2": "You will lose access to all projects this team has access to. If you change your mind you'll need a team admin to add you again.",
"success": "You have successfully left the team." "success": "You have successfully left the team."
} }
}, },
@ -894,7 +828,10 @@
"color": "Change the color of this task", "color": "Change the color of this task",
"move": "Move this task to another project", "move": "Move this task to another project",
"reminder": "Manage reminders of this task", "reminder": "Manage reminders of this task",
"description": "Toggle editing of the task description" "description": "Toggle editing of the task description",
"delete": "Delete this task",
"priority": "Change the priority of this task",
"favorite": "Mark this task as favorite / unfavorite"
}, },
"project": { "project": {
"title": "Project Views", "title": "Project Views",
@ -907,9 +844,9 @@
"title": "Navigation", "title": "Navigation",
"overview": "Navigate to overview", "overview": "Navigate to overview",
"upcoming": "Navigate to upcoming tasks", "upcoming": "Navigate to upcoming tasks",
"namespaces": "Navigate to namespaces & projects",
"labels": "Navigate to labels", "labels": "Navigate to labels",
"teams": "Navigate to teams" "teams": "Navigate to teams",
"projects": "Navigate to projects"
} }
}, },
"update": { "update": {
@ -924,7 +861,8 @@
"unarchive": "Un-Archive", "unarchive": "Un-Archive",
"setBackground": "Set background", "setBackground": "Set background",
"share": "Share", "share": "Share",
"newProject": "New project" "newProject": "New project",
"createProject": "Create project"
}, },
"apiConfig": { "apiConfig": {
"url": "Vikunja URL", "url": "Vikunja URL",
@ -943,7 +881,7 @@
"notification": { "notification": {
"title": "Notifications", "title": "Notifications",
"none": "You don't have any notifications. Have a nice day!", "none": "You don't have any notifications. Have a nice day!",
"explainer": "Notifications will appear here when actions on namespaces, projects or tasks you subscribed to happen." "explainer": "Notifications will appear here when actions projects or tasks you subscribed to happen."
}, },
"quickActions": { "quickActions": {
"commands": "Commands", "commands": "Commands",
@ -954,14 +892,12 @@
"teams": "Teams", "teams": "Teams",
"newProject": "Enter the title of the new project…", "newProject": "Enter the title of the new project…",
"newTask": "Enter the title of the new task…", "newTask": "Enter the title of the new task…",
"newNamespace": "Enter the title of the new namespace…",
"newTeam": "Enter the name of the new team…", "newTeam": "Enter the name of the new team…",
"createTask": "Create a task in the current project ({title})", "createTask": "Create a task in the current project ({title})",
"createProject": "Create a project in the current namespace ({title})", "createProject": "Create a project",
"cmds": { "cmds": {
"newTask": "New task", "newTask": "New task",
"newProject": "New project", "newProject": "New project",
"newNamespace": "New namespace",
"newTeam": "New team" "newTeam": "New team"
} }
}, },
@ -1017,16 +953,9 @@
"4017": "Invalid task filter comparator.", "4017": "Invalid task filter comparator.",
"4018": "Invalid task filter concatenator.", "4018": "Invalid task filter concatenator.",
"4019": "Invalid task filter value.", "4019": "Invalid task filter value.",
"5001": "The namespace does not exist.",
"5003": "You do not have access to the specified namespace.",
"5006": "The namespace name cannot be empty.",
"5009": "You need to have namespace read access to perform that action.",
"5010": "This team does not have access to that namespace.",
"5011": "This user has already access to that namespace.",
"5012": "The namespace is archived and can therefore only be accessed read only.",
"6001": "The team name cannot be empty.", "6001": "The team name cannot be empty.",
"6002": "The team does not exist.", "6002": "The team does not exist.",
"6004": "The team already has access to that namespace or project.", "6004": "The team already has access to that project.",
"6005": "The user is already a member of that team.", "6005": "The user is already a member of that team.",
"6006": "Cannot delete the last team member.", "6006": "Cannot delete the last team member.",
"6007": "The team does not have access to the project to perform that action.", "6007": "The team does not have access to the project to perform that action.",
@ -1053,4 +982,4 @@
"frontendVersion": "Frontend Version: {version}", "frontendVersion": "Frontend Version: {version}",
"apiVersion": "API Version: {version}" "apiVersion": "API Version: {version}"
} }
} }

View File

@ -6,9 +6,7 @@
"welcomeEvening": "Добрый вечер, {username}!", "welcomeEvening": "Добрый вечер, {username}!",
"lastViewed": "Последние просмотренные", "lastViewed": "Последние просмотренные",
"project": { "project": {
"newText": "Вы можете создать новый проект для своих задач:", "importText": "Import your projects and tasks from other services into Vikunja:",
"new": "Создать проект",
"importText": "Или импортировать проекты и задачи из других сервисов в Vikunja:",
"import": "Импорт данных в Vikunja" "import": "Импорт данных в Vikunja"
} }
}, },
@ -143,7 +141,7 @@
}, },
"deletion": { "deletion": {
"title": "Удалить свой аккаунт VIkunja", "title": "Удалить свой аккаунт VIkunja",
"text1": "Удаление аккаунта необратимо. Мы удалим все ваши пространства имён, проекты, задачи и всё связанное с ними.", "text1": "The deletion of your account is permanent and cannot be undone. We will delete all your projects, tasks and everything associated with it.",
"text2": "Для продолжения введите свой пароль. На почту будет отправлено письмо с дальнейшими инструкциями.", "text2": "Для продолжения введите свой пароль. На почту будет отправлено письмо с дальнейшими инструкциями.",
"confirm": "Удалить мой аккаунт", "confirm": "Удалить мой аккаунт",
"requestSuccess": "Запрос успешно выполнен. На почту будет отправлено письмо с дальнейшими инструкциями.", "requestSuccess": "Запрос успешно выполнен. На почту будет отправлено письмо с дальнейшими инструкциями.",
@ -157,7 +155,7 @@
}, },
"export": { "export": {
"title": "Экспорт данных Vikunja", "title": "Экспорт данных Vikunja",
"description": "Вы можете запросить копию всех своих данных Vikunja. Это включает в себя пространства имён, проекты, задачи и всё связанное с ними. Эти данные можно будет импортировать на любом экземпляре Vikunja через функцию миграции.", "description": "You can request a copy of all your Vikunja data. This includes Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
"descriptionPasswordRequired": "Для продолжения введите свой пароль:", "descriptionPasswordRequired": "Для продолжения введите свой пароль:",
"request": "Запросить копию моих данных Vikunja", "request": "Запросить копию моих данных Vikunja",
"success": "Данные Vikunja успешно запрошены! На почту придёт письмо, когда они будут готовы для скачивания.", "success": "Данные Vikunja успешно запрошены! На почту придёт письмо, когда они будут готовы для скачивания.",
@ -165,14 +163,18 @@
} }
}, },
"project": { "project": {
"archived": "Этот проект архивирован. В нём нельзя создавать или изменять задачи.", "archivedMessage": "This project is archived. It is not possible to create new or edit tasks for it.",
"archived": "Archived",
"showArchived": "Show Archived",
"title": "Название проекта", "title": "Название проекта",
"color": "Цвет", "color": "Цвет",
"projects": "Проекты", "projects": "Проекты",
"parent": "Parent Project",
"search": "Введите запрос для поиска проекта…", "search": "Введите запрос для поиска проекта…",
"searchSelect": "Кликните или нажмите Enter для выбора этого проекта", "searchSelect": "Кликните или нажмите Enter для выбора этого проекта",
"shared": "Shared Projects", "shared": "Shared Projects",
"noDescriptionAvailable": "Описание проекта отсутствует.", "noDescriptionAvailable": "Описание проекта отсутствует.",
"inboxTitle": "Inbox",
"create": { "create": {
"header": "Создать проект", "header": "Создать проект",
"titlePlaceholder": "Введите название проекта…", "titlePlaceholder": "Введите название проекта…",
@ -210,7 +212,7 @@
"duplicate": { "duplicate": {
"title": "Создание копии проекта", "title": "Создание копии проекта",
"label": "Создать копию", "label": "Создать копию",
"text": "Пространство имён, в которое поместить копию проекта:", "text": "Select a parent project which should hold the duplicated project:",
"success": "Копия проекта создана." "success": "Копия проекта создана."
}, },
"edit": { "edit": {
@ -321,67 +323,6 @@
} }
} }
}, },
"namespace": {
"title": "Пространства имён и проекты",
"namespace": "Пространство имён",
"showArchived": "Показать архив",
"noneAvailable": "Пространств имён сейчас нет.",
"unarchive": "Вернуть из архива",
"archived": "Архивировано",
"noProjects": "В этом пространстве имён нет ни одного проекта.",
"createProject": "Создать новый проект в этом пространстве имён.",
"namespaces": "Пространства имён",
"search": "Введите запрос для поиска пространства имён…",
"create": {
"title": "Создать пространство имён",
"titleRequired": "Пожалуйста, укажите название.",
"explanation": "Это коллекция проектов, которым можно поделиться и который можно использовать для упорядочивания проектов. Фактически, каждый проект принадлежит какому-нибудь пространству имён.",
"tooltip": "Что такое пространство имён?",
"success": "Пространство имён создано."
},
"archive": {
"titleArchive": "Архивировать «{namespace}»",
"titleUnarchive": "Вернуть «{namespace}» из архива",
"archiveText": "Вы не сможете изменять это пространство имён, пока не вернёте его из архива. Это также касается всех проектов в этом пространстве имён.",
"unarchiveText": "Вы сможете создавать новые проекты или изменять их.",
"success": "Пространство имён архивировано.",
"unarchiveSuccess": "Пространство имён разархивировано.",
"description": "Архивирование пространства имён означает, что вы не сможете создавать в нём новые проекты или изменять их."
},
"delete": {
"title": "Удалить «{namespace}»",
"text1": "Удалить это пространство имён вместе со всем содержимым?",
"text2": "Это включает в себя все проекты и задачи, и отменить это будет нельзя!",
"success": "Пространство имён удалено."
},
"edit": {
"title": "Изменить «{namespace}»",
"success": "Пространство имён обновлено."
},
"share": {
"title": "Поделиться пространством имён «{namespace}»"
},
"attributes": {
"title": "Название пространства имён",
"titlePlaceholder": "Введи название пространства имён…",
"description": "Описание",
"descriptionPlaceholder": "Введи описание пространства имён…",
"color": "Цвет",
"archived": "Архивировано",
"isArchived": "Это пространство имён архивировано"
},
"pseudo": {
"sharedProjects": {
"title": "Shared Projects"
},
"favorites": {
"title": "Избранное"
},
"savedFilters": {
"title": "Фильтры"
}
}
},
"filters": { "filters": {
"title": "Фильтры", "title": "Фильтры",
"clear": "Сбросить фильтры", "clear": "Сбросить фильтры",
@ -403,7 +344,7 @@
}, },
"create": { "create": {
"title": "Создать сохранённый фильтр", "title": "Создать сохранённый фильтр",
"description": "Сохранённый фильтр — это виртуальный проект, построенный из набора фильтров. При создании отображается в специальном пространстве имён.", "description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed.",
"action": "Создать новый сохранённый фильтр", "action": "Создать новый сохранённый фильтр",
"titleRequired": "Укажите название фильтра." "titleRequired": "Укажите название фильтра."
}, },
@ -674,19 +615,13 @@
"updated": "Дата изменения" "updated": "Дата изменения"
}, },
"subscription": { "subscription": {
"subscribedProjectThroughParentNamespace": "Вы не можете отписаться здесь, потому что вы подписаны на проект через его пространство имён.",
"subscribedTaskThroughParentNamespace": "Вы не можете отписаться здесь, потому что вы подписаны на эту задачу через её пространство имён.",
"subscribedTaskThroughParentProject": "Вы не можете отписаться здесь, потому что вы подписаны эту задачу через её проект.", "subscribedTaskThroughParentProject": "Вы не можете отписаться здесь, потому что вы подписаны эту задачу через её проект.",
"subscribedNamespace": "Вы подписаны на это пространство имён и будете получать уведомления об изменениях.",
"notSubscribedNamespace": "Вы не подписаны на это пространство имён и не будете получать уведомления об изменениях.",
"subscribedProject": "Вы подписаны на этот проект и будете получать уведомления об изменениях.", "subscribedProject": "Вы подписаны на этот проект и будете получать уведомления об изменениях.",
"notSubscribedProject": "Вы не подписаны на этот проект и не будете получать уведомления об изменениях.", "notSubscribedProject": "Вы не подписаны на этот проект и не будете получать уведомления об изменениях.",
"subscribedTask": "Вы подписаны на эту задачу и будете получать уведомления об изменениях.", "subscribedTask": "Вы подписаны на эту задачу и будете получать уведомления об изменениях.",
"notSubscribedTask": "Вы не подписаны на эту задачу и не будете получать уведомления об изменениях.", "notSubscribedTask": "Вы не подписаны на эту задачу и не будете получать уведомления об изменениях.",
"subscribe": "Подписаться", "subscribe": "Подписаться",
"unsubscribe": "Отписаться", "unsubscribe": "Отписаться",
"subscribeSuccessNamespace": "Подписка на пространство имён оформлена",
"unsubscribeSuccessNamespace": "Подписка на пространство имён удалена",
"subscribeSuccessProject": "Подписка на проект оформлена", "subscribeSuccessProject": "Подписка на проект оформлена",
"unsubscribeSuccessProject": "Подписка на проект удалена", "unsubscribeSuccessProject": "Подписка на проект удалена",
"subscribeSuccessTask": "Подписка на задачу оформлена", "subscribeSuccessTask": "Подписка на задачу оформлена",
@ -763,7 +698,6 @@
"searchPlaceholder": "Введи запрос для поиска задачи, чтобы добавить связь…", "searchPlaceholder": "Введи запрос для поиска задачи, чтобы добавить связь…",
"createPlaceholder": "Добавить как связанную задачу", "createPlaceholder": "Добавить как связанную задачу",
"differentProject": "Эта задача принадлежит другому проекту.", "differentProject": "Эта задача принадлежит другому проекту.",
"differentNamespace": "Эта задача принадлежит другому пространству имён.",
"noneYet": "Ещё нет связанных задач.", "noneYet": "Ещё нет связанных задач.",
"delete": "Удалить связь", "delete": "Удалить связь",
"deleteText1": "Удалить эту связь с задачей?", "deleteText1": "Удалить эту связь с задачей?",
@ -848,19 +782,19 @@
"delete": { "delete": {
"header": "Удалить команду", "header": "Удалить команду",
"text1": "Удалить эту команду вместе с участниками?", "text1": "Удалить эту команду вместе с участниками?",
"text2": "Все участники команды потеряют доступ к проектам и пространствам имён, которыми поделились с этой командой. Это действие отменить НЕЛЬЗЯ!", "text2": "All team members will lose access to projects shared with this team. This CANNOT BE UNDONE!",
"success": "Команда удалена." "success": "Команда удалена."
}, },
"deleteUser": { "deleteUser": {
"header": "Удалить пользователя из команды", "header": "Удалить пользователя из команды",
"text1": "Удалить этого пользователя из команды?", "text1": "Удалить этого пользователя из команды?",
"text2": "Пользователь потеряет доступ ко всем проектам и пространствам имён, к которым есть доступ у команды. Это действие отменить нельзя!", "text2": "They will lose access to all projects this team has access to. This CANNOT BE UNDONE!",
"success": "Пользователь удалён из команды." "success": "Пользователь удалён из команды."
}, },
"leave": { "leave": {
"title": "Покинуть команду", "title": "Покинуть команду",
"text1": "Покинуть эту команду?", "text1": "Покинуть эту команду?",
"text2": "Вы потеряете доступ ко всем проектам и пространствам имён, к которым есть доступ у команды. Если вы передумаете, придётся просить администратора команды добавить вас снова.", "text2": "You will lose access to all projects this team has access to. If you change your mind you'll need a team admin to add you again.",
"success": "Вы покинули команду." "success": "Вы покинули команду."
} }
}, },
@ -894,7 +828,10 @@
"color": "Изменить цвет этой задачи", "color": "Изменить цвет этой задачи",
"move": "Переместить эту задачу в другой проект", "move": "Переместить эту задачу в другой проект",
"reminder": "Управление напоминаниями об этой задаче", "reminder": "Управление напоминаниями об этой задаче",
"description": "Включить изменение описания задачи" "description": "Включить изменение описания задачи",
"delete": "Удалить задачу",
"priority": "Изменить приоритет задачи",
"favorite": "Mark this task as favorite / unfavorite"
}, },
"project": { "project": {
"title": "Просмотр проекта", "title": "Просмотр проекта",
@ -907,9 +844,9 @@
"title": "Навигация", "title": "Навигация",
"overview": "Перейти к странице обзора", "overview": "Перейти к странице обзора",
"upcoming": "Перейти к предстоящим задачам", "upcoming": "Перейти к предстоящим задачам",
"namespaces": "Перейти к пространствам имён и проектам",
"labels": "Перейти к меткам", "labels": "Перейти к меткам",
"teams": "Перейти к командам" "teams": "Перейти к командам",
"projects": "Navigate to projects"
} }
}, },
"update": { "update": {
@ -924,7 +861,8 @@
"unarchive": "Вернуть из архива", "unarchive": "Вернуть из архива",
"setBackground": "Задать фон", "setBackground": "Задать фон",
"share": "Поделиться", "share": "Поделиться",
"newProject": "Создать проект" "newProject": "Создать проект",
"createProject": "Create project"
}, },
"apiConfig": { "apiConfig": {
"url": "Vikunja URL", "url": "Vikunja URL",
@ -943,7 +881,7 @@
"notification": { "notification": {
"title": "Уведомления", "title": "Уведомления",
"none": "Уведомлений нет. Хорошего дня!", "none": "Уведомлений нет. Хорошего дня!",
"explainer": "Здесь появятся уведомления, когда что-нибудь произойдёт с пространствами имён, проектами или задачами, на которые вы подписаны." "explainer": "Notifications will appear here when actions projects or tasks you subscribed to happen."
}, },
"quickActions": { "quickActions": {
"commands": "Команды", "commands": "Команды",
@ -954,14 +892,12 @@
"teams": "Команды", "teams": "Команды",
"newProject": "Введите название проекта…", "newProject": "Введите название проекта…",
"newTask": "Введите название задачи…", "newTask": "Введите название задачи…",
"newNamespace": "Введите название пространства имён…",
"newTeam": "Введите название новой команды…", "newTeam": "Введите название новой команды…",
"createTask": "Создать задачу в текущем проекте ({title})", "createTask": "Создать задачу в текущем проекте ({title})",
"createProject": "Создать проект в текущем пространстве имён ({title})", "createProject": "Create a project",
"cmds": { "cmds": {
"newTask": "Новая задача", "newTask": "Новая задача",
"newProject": "Создать проект", "newProject": "Создать проект",
"newNamespace": "Новое пространство имён",
"newTeam": "Новая команда" "newTeam": "Новая команда"
} }
}, },
@ -1017,16 +953,9 @@
"4017": "Неверный сравнитель фильтров задач.", "4017": "Неверный сравнитель фильтров задач.",
"4018": "Неверный соединитель фильтров задач.", "4018": "Неверный соединитель фильтров задач.",
"4019": "Неверное значение фильтра задач.", "4019": "Неверное значение фильтра задач.",
"5001": "Пространство имён не существует.",
"5003": "Нет доступа к указанному пространству имён.",
"5006": "Название пространства имён не может быть пустым.",
"5009": "Для этого действия необходим доступ на чтение пространства имён.",
"5010": "У этой команды нет доступа к этому пространству имён.",
"5011": "Этот пользователь уже имеет доступ к этому пространству имён.",
"5012": "Это пространство имён архивировано и поэтому доступно только для чтения.",
"6001": "Имя команды не может быть пустым.", "6001": "Имя команды не может быть пустым.",
"6002": "Команда не существует.", "6002": "Команда не существует.",
"6004": "Эта команда уже имеет доступ к этому пространству имён или проекту.", "6004": "The team already has access to that project.",
"6005": "Пользователь уже является участником этой команды.", "6005": "Пользователь уже является участником этой команды.",
"6006": "Нельзя удалить последнего участника команды.", "6006": "Нельзя удалить последнего участника команды.",
"6007": "У команды нет доступа к проекту, чтобы выполнить это действие.", "6007": "У команды нет доступа к проекту, чтобы выполнить это действие.",
@ -1053,4 +982,4 @@
"frontendVersion": "Версия фронтенда: {version}", "frontendVersion": "Версия фронтенда: {version}",
"apiVersion": "Версия API: {version}" "apiVersion": "Версия API: {version}"
} }
} }

View File

@ -6,9 +6,7 @@
"welcomeEvening": "Good Evening {username}!", "welcomeEvening": "Good Evening {username}!",
"lastViewed": "Last viewed", "lastViewed": "Last viewed",
"project": { "project": {
"newText": "You can create a new project for your new tasks:", "importText": "Import your projects and tasks from other services into Vikunja:",
"new": "New project",
"importText": "Or import your projects and tasks from other services into Vikunja:",
"import": "Import your data into Vikunja" "import": "Import your data into Vikunja"
} }
}, },
@ -143,7 +141,7 @@
}, },
"deletion": { "deletion": {
"title": "Delete your Vikunja Account", "title": "Delete your Vikunja Account",
"text1": "The deletion of your account is permanent and cannot be undone. We will delete all your namespaces, projects, tasks and everything associated with it.", "text1": "The deletion of your account is permanent and cannot be undone. We will delete all your projects, tasks and everything associated with it.",
"text2": "To proceed, please enter your password. You will receive an email with further instructions.", "text2": "To proceed, please enter your password. You will receive an email with further instructions.",
"confirm": "Delete my account", "confirm": "Delete my account",
"requestSuccess": "The request was successful. You'll receive an email with further instructions.", "requestSuccess": "The request was successful. You'll receive an email with further instructions.",
@ -157,7 +155,7 @@
}, },
"export": { "export": {
"title": "Export your Vikunja data", "title": "Export your Vikunja data",
"description": "You can request a copy of all your Vikunja data. This include Namespaces, Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.", "description": "You can request a copy of all your Vikunja data. This includes Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
"descriptionPasswordRequired": "Please enter your password to proceed:", "descriptionPasswordRequired": "Please enter your password to proceed:",
"request": "Request a copy of my Vikunja Data", "request": "Request a copy of my Vikunja Data",
"success": "You've successfully requested your Vikunja Data! We will send you an email once it's ready to download.", "success": "You've successfully requested your Vikunja Data! We will send you an email once it's ready to download.",
@ -165,14 +163,18 @@
} }
}, },
"project": { "project": {
"archived": "This project is archived. It is not possible to create new or edit tasks for it.", "archivedMessage": "This project is archived. It is not possible to create new or edit tasks for it.",
"archived": "Archived",
"showArchived": "Show Archived",
"title": "Project Title", "title": "Project Title",
"color": "Color", "color": "Color",
"projects": "Projects", "projects": "Projects",
"parent": "Parent Project",
"search": "Type to search for a project…", "search": "Type to search for a project…",
"searchSelect": "Click or press enter to select this project", "searchSelect": "Click or press enter to select this project",
"shared": "Shared Projects", "shared": "Shared Projects",
"noDescriptionAvailable": "No project description is available.", "noDescriptionAvailable": "No project description is available.",
"inboxTitle": "Inbox",
"create": { "create": {
"header": "New project", "header": "New project",
"titlePlaceholder": "The project's title goes here…", "titlePlaceholder": "The project's title goes here…",
@ -210,7 +212,7 @@
"duplicate": { "duplicate": {
"title": "Duplicate this project", "title": "Duplicate this project",
"label": "Duplicate", "label": "Duplicate",
"text": "Select a namespace which should hold the duplicated project:", "text": "Select a parent project which should hold the duplicated project:",
"success": "The project was successfully duplicated." "success": "The project was successfully duplicated."
}, },
"edit": { "edit": {
@ -321,67 +323,6 @@
} }
} }
}, },
"namespace": {
"title": "Namespaces & Projects",
"namespace": "Namespace",
"showArchived": "Show Archived",
"noneAvailable": "You don't have any namespaces right now.",
"unarchive": "Un-Archive",
"archived": "Archived",
"noProjects": "This namespace does not contain any projects.",
"createProject": "Create a new project in this namespace.",
"namespaces": "Namespaces",
"search": "Type to search for a namespace…",
"create": {
"title": "New namespace",
"titleRequired": "Please specify a title.",
"explanation": "A namespace is a collection of projects you can share and use to organize your projects with. In fact, every project belongs to a namespace.",
"tooltip": "What's a namespace?",
"success": "The namespace was successfully created."
},
"archive": {
"titleArchive": "Archive \"{namespace}\"",
"titleUnarchive": "Un-Archive \"{namespace}\"",
"archiveText": "You won't be able to edit this namespace or create new projects until you un-archive it. This will also archive all projects in this namespace.",
"unarchiveText": "You will be able to create new projects or edit it.",
"success": "The namespace was successfully archived.",
"unarchiveSuccess": "The namespace was successfully un-archived.",
"description": "If a namespace is archived, you cannot create new projects or edit it."
},
"delete": {
"title": "Delete \"{namespace}\"",
"text1": "Are you sure you want to delete this namespace and all of its contents?",
"text2": "This includes all projects and tasks and CANNOT BE UNDONE!",
"success": "The namespace was successfully deleted."
},
"edit": {
"title": "Edit \"{namespace}\"",
"success": "The namespace was successfully updated."
},
"share": {
"title": "Share \"{namespace}\""
},
"attributes": {
"title": "Namespace Title",
"titlePlaceholder": "The namespace title goes here…",
"description": "Description",
"descriptionPlaceholder": "The namespaces description goes here…",
"color": "Color",
"archived": "Is Archived",
"isArchived": "This namespace is archived"
},
"pseudo": {
"sharedProjects": {
"title": "Shared Projects"
},
"favorites": {
"title": "Favorites"
},
"savedFilters": {
"title": "Filters"
}
}
},
"filters": { "filters": {
"title": "Filters", "title": "Filters",
"clear": "Clear Filters", "clear": "Clear Filters",
@ -403,7 +344,7 @@
}, },
"create": { "create": {
"title": "New Saved Filter", "title": "New Saved Filter",
"description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed. Once created, it will appear in a special namespace.", "description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed.",
"action": "Create new saved filter", "action": "Create new saved filter",
"titleRequired": "Please provide a title for the filter." "titleRequired": "Please provide a title for the filter."
}, },
@ -674,19 +615,13 @@
"updated": "Updated" "updated": "Updated"
}, },
"subscription": { "subscription": {
"subscribedProjectThroughParentNamespace": "You can't unsubscribe here because you are subscribed to this project through its namespace.",
"subscribedTaskThroughParentNamespace": "You can't unsubscribe here because you are subscribed to this task through its namespace.",
"subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.", "subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.",
"subscribedNamespace": "You are currently subscribed to this namespace and will receive notifications for changes.",
"notSubscribedNamespace": "You are not subscribed to this namespace and won't receive notifications for changes.",
"subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.", "subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.",
"notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.", "notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.",
"subscribedTask": "You are currently subscribed to this task and will receive notifications for changes.", "subscribedTask": "You are currently subscribed to this task and will receive notifications for changes.",
"notSubscribedTask": "You are not subscribed to this task and won't receive notifications for changes.", "notSubscribedTask": "You are not subscribed to this task and won't receive notifications for changes.",
"subscribe": "Subscribe", "subscribe": "Subscribe",
"unsubscribe": "Unsubscribe", "unsubscribe": "Unsubscribe",
"subscribeSuccessNamespace": "You are now subscribed to this namespace",
"unsubscribeSuccessNamespace": "You are now unsubscribed to this namespace",
"subscribeSuccessProject": "You are now subscribed to this project", "subscribeSuccessProject": "You are now subscribed to this project",
"unsubscribeSuccessProject": "You are now unsubscribed to this project", "unsubscribeSuccessProject": "You are now unsubscribed to this project",
"subscribeSuccessTask": "You are now subscribed to this task", "subscribeSuccessTask": "You are now subscribed to this task",
@ -763,7 +698,6 @@
"searchPlaceholder": "Type search for a new task to add as related…", "searchPlaceholder": "Type search for a new task to add as related…",
"createPlaceholder": "Add this as new related task", "createPlaceholder": "Add this as new related task",
"differentProject": "This task belongs to a different project.", "differentProject": "This task belongs to a different project.",
"differentNamespace": "This task belongs to a different namespace.",
"noneYet": "No task relations yet.", "noneYet": "No task relations yet.",
"delete": "Delete Task Relation", "delete": "Delete Task Relation",
"deleteText1": "Are you sure you want to delete this task relation?", "deleteText1": "Are you sure you want to delete this task relation?",
@ -848,19 +782,19 @@
"delete": { "delete": {
"header": "Delete the team", "header": "Delete the team",
"text1": "Are you sure you want to delete this team and all of its members?", "text1": "Are you sure you want to delete this team and all of its members?",
"text2": "All team members will lose access to projects and namespaces shared with this team. This CANNOT BE UNDONE!", "text2": "All team members will lose access to projects shared with this team. This CANNOT BE UNDONE!",
"success": "The team was successfully deleted." "success": "The team was successfully deleted."
}, },
"deleteUser": { "deleteUser": {
"header": "Remove a user from the team", "header": "Remove a user from the team",
"text1": "Are you sure you want to remove this user from the team?", "text1": "Are you sure you want to remove this user from the team?",
"text2": "They will lose access to all projects and namespaces this team has access to. This CANNOT BE UNDONE!", "text2": "They will lose access to all projects this team has access to. This CANNOT BE UNDONE!",
"success": "The user was successfully deleted from the team." "success": "The user was successfully deleted from the team."
}, },
"leave": { "leave": {
"title": "Leave team", "title": "Leave team",
"text1": "Are you sure you want to leave this team?", "text1": "Are you sure you want to leave this team?",
"text2": "You will lose access to all projects and namespaces this team has access to. If you change your mind you'll need a team admin to add you again.", "text2": "You will lose access to all projects this team has access to. If you change your mind you'll need a team admin to add you again.",
"success": "You have successfully left the team." "success": "You have successfully left the team."
} }
}, },
@ -894,7 +828,10 @@
"color": "Change the color of this task", "color": "Change the color of this task",
"move": "Move this task to another project", "move": "Move this task to another project",
"reminder": "Manage reminders of this task", "reminder": "Manage reminders of this task",
"description": "Toggle editing of the task description" "description": "Toggle editing of the task description",
"delete": "Delete this task",
"priority": "Change the priority of this task",
"favorite": "Mark this task as favorite / unfavorite"
}, },
"project": { "project": {
"title": "Project Views", "title": "Project Views",
@ -907,9 +844,9 @@
"title": "Navigation", "title": "Navigation",
"overview": "Navigate to overview", "overview": "Navigate to overview",
"upcoming": "Navigate to upcoming tasks", "upcoming": "Navigate to upcoming tasks",
"namespaces": "Navigate to namespaces & projects",
"labels": "Navigate to labels", "labels": "Navigate to labels",
"teams": "Navigate to teams" "teams": "Navigate to teams",
"projects": "Navigate to projects"
} }
}, },
"update": { "update": {
@ -924,7 +861,8 @@
"unarchive": "Un-Archive", "unarchive": "Un-Archive",
"setBackground": "Set background", "setBackground": "Set background",
"share": "Share", "share": "Share",
"newProject": "New project" "newProject": "New project",
"createProject": "Create project"
}, },
"apiConfig": { "apiConfig": {
"url": "Vikunja URL", "url": "Vikunja URL",
@ -943,7 +881,7 @@
"notification": { "notification": {
"title": "Notifications", "title": "Notifications",
"none": "You don't have any notifications. Have a nice day!", "none": "You don't have any notifications. Have a nice day!",
"explainer": "Notifications will appear here when actions on namespaces, projects or tasks you subscribed to happen." "explainer": "Notifications will appear here when actions projects or tasks you subscribed to happen."
}, },
"quickActions": { "quickActions": {
"commands": "Commands", "commands": "Commands",
@ -954,14 +892,12 @@
"teams": "Teams", "teams": "Teams",
"newProject": "Enter the title of the new project…", "newProject": "Enter the title of the new project…",
"newTask": "Enter the title of the new task…", "newTask": "Enter the title of the new task…",
"newNamespace": "Enter the title of the new namespace…",
"newTeam": "Enter the name of the new team…", "newTeam": "Enter the name of the new team…",
"createTask": "Create a task in the current project ({title})", "createTask": "Create a task in the current project ({title})",
"createProject": "Create a project in the current namespace ({title})", "createProject": "Create a project",
"cmds": { "cmds": {
"newTask": "New task", "newTask": "New task",
"newProject": "New project", "newProject": "New project",
"newNamespace": "New namespace",
"newTeam": "New team" "newTeam": "New team"
} }
}, },
@ -1017,16 +953,9 @@
"4017": "Invalid task filter comparator.", "4017": "Invalid task filter comparator.",
"4018": "Invalid task filter concatenator.", "4018": "Invalid task filter concatenator.",
"4019": "Invalid task filter value.", "4019": "Invalid task filter value.",
"5001": "The namespace does not exist.",
"5003": "You do not have access to the specified namespace.",
"5006": "The namespace name cannot be empty.",
"5009": "You need to have namespace read access to perform that action.",
"5010": "This team does not have access to that namespace.",
"5011": "This user has already access to that namespace.",
"5012": "The namespace is archived and can therefore only be accessed read only.",
"6001": "The team name cannot be empty.", "6001": "The team name cannot be empty.",
"6002": "The team does not exist.", "6002": "The team does not exist.",
"6004": "The team already has access to that namespace or project.", "6004": "The team already has access to that project.",
"6005": "The user is already a member of that team.", "6005": "The user is already a member of that team.",
"6006": "Cannot delete the last team member.", "6006": "Cannot delete the last team member.",
"6007": "The team does not have access to the project to perform that action.", "6007": "The team does not have access to the project to perform that action.",
@ -1053,4 +982,4 @@
"frontendVersion": "Frontend Version: {version}", "frontendVersion": "Frontend Version: {version}",
"apiVersion": "API Version: {version}" "apiVersion": "API Version: {version}"
} }
} }

View File

@ -6,9 +6,7 @@
"welcomeEvening": "Good Evening {username}!", "welcomeEvening": "Good Evening {username}!",
"lastViewed": "Last viewed", "lastViewed": "Last viewed",
"project": { "project": {
"newText": "You can create a new project for your new tasks:", "importText": "Import your projects and tasks from other services into Vikunja:",
"new": "New project",
"importText": "Or import your projects and tasks from other services into Vikunja:",
"import": "Import your data into Vikunja" "import": "Import your data into Vikunja"
} }
}, },
@ -143,7 +141,7 @@
}, },
"deletion": { "deletion": {
"title": "Delete your Vikunja Account", "title": "Delete your Vikunja Account",
"text1": "The deletion of your account is permanent and cannot be undone. We will delete all your namespaces, projects, tasks and everything associated with it.", "text1": "The deletion of your account is permanent and cannot be undone. We will delete all your projects, tasks and everything associated with it.",
"text2": "To proceed, please enter your password. You will receive an email with further instructions.", "text2": "To proceed, please enter your password. You will receive an email with further instructions.",
"confirm": "Delete my account", "confirm": "Delete my account",
"requestSuccess": "The request was successful. You'll receive an email with further instructions.", "requestSuccess": "The request was successful. You'll receive an email with further instructions.",
@ -157,7 +155,7 @@
}, },
"export": { "export": {
"title": "Export your Vikunja data", "title": "Export your Vikunja data",
"description": "You can request a copy of all your Vikunja data. This include Namespaces, Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.", "description": "You can request a copy of all your Vikunja data. This includes Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
"descriptionPasswordRequired": "Please enter your password to proceed:", "descriptionPasswordRequired": "Please enter your password to proceed:",
"request": "Request a copy of my Vikunja Data", "request": "Request a copy of my Vikunja Data",
"success": "You've successfully requested your Vikunja Data! We will send you an email once it's ready to download.", "success": "You've successfully requested your Vikunja Data! We will send you an email once it's ready to download.",
@ -165,14 +163,18 @@
} }
}, },
"project": { "project": {
"archived": "This project is archived. It is not possible to create new or edit tasks for it.", "archivedMessage": "This project is archived. It is not possible to create new or edit tasks for it.",
"archived": "Archived",
"showArchived": "Show Archived",
"title": "Project Title", "title": "Project Title",
"color": "Color", "color": "Color",
"projects": "Projects", "projects": "Projects",
"parent": "Parent Project",
"search": "Type to search for a project…", "search": "Type to search for a project…",
"searchSelect": "Click or press enter to select this project", "searchSelect": "Click or press enter to select this project",
"shared": "Shared Projects", "shared": "Shared Projects",
"noDescriptionAvailable": "No project description is available.", "noDescriptionAvailable": "No project description is available.",
"inboxTitle": "Inbox",
"create": { "create": {
"header": "New project", "header": "New project",
"titlePlaceholder": "The project's title goes here…", "titlePlaceholder": "The project's title goes here…",
@ -210,7 +212,7 @@
"duplicate": { "duplicate": {
"title": "Duplicate this project", "title": "Duplicate this project",
"label": "Duplicate", "label": "Duplicate",
"text": "Select a namespace which should hold the duplicated project:", "text": "Select a parent project which should hold the duplicated project:",
"success": "The project was successfully duplicated." "success": "The project was successfully duplicated."
}, },
"edit": { "edit": {
@ -321,67 +323,6 @@
} }
} }
}, },
"namespace": {
"title": "Namespaces & Projects",
"namespace": "Namespace",
"showArchived": "Show Archived",
"noneAvailable": "You don't have any namespaces right now.",
"unarchive": "Un-Archive",
"archived": "Archived",
"noProjects": "This namespace does not contain any projects.",
"createProject": "Create a new project in this namespace.",
"namespaces": "Namespaces",
"search": "Type to search for a namespace…",
"create": {
"title": "New namespace",
"titleRequired": "Please specify a title.",
"explanation": "A namespace is a collection of projects you can share and use to organize your projects with. In fact, every project belongs to a namespace.",
"tooltip": "What's a namespace?",
"success": "The namespace was successfully created."
},
"archive": {
"titleArchive": "Archive \"{namespace}\"",
"titleUnarchive": "Un-Archive \"{namespace}\"",
"archiveText": "You won't be able to edit this namespace or create new projects until you un-archive it. This will also archive all projects in this namespace.",
"unarchiveText": "You will be able to create new projects or edit it.",
"success": "The namespace was successfully archived.",
"unarchiveSuccess": "The namespace was successfully un-archived.",
"description": "If a namespace is archived, you cannot create new projects or edit it."
},
"delete": {
"title": "Delete \"{namespace}\"",
"text1": "Are you sure you want to delete this namespace and all of its contents?",
"text2": "This includes all projects and tasks and CANNOT BE UNDONE!",
"success": "The namespace was successfully deleted."
},
"edit": {
"title": "Edit \"{namespace}\"",
"success": "The namespace was successfully updated."
},
"share": {
"title": "Share \"{namespace}\""
},
"attributes": {
"title": "Namespace Title",
"titlePlaceholder": "The namespace title goes here…",
"description": "Description",
"descriptionPlaceholder": "The namespaces description goes here…",
"color": "Color",
"archived": "Is Archived",
"isArchived": "This namespace is archived"
},
"pseudo": {
"sharedProjects": {
"title": "Shared Projects"
},
"favorites": {
"title": "Favorites"
},
"savedFilters": {
"title": "Filters"
}
}
},
"filters": { "filters": {
"title": "Filters", "title": "Filters",
"clear": "Clear Filters", "clear": "Clear Filters",
@ -403,7 +344,7 @@
}, },
"create": { "create": {
"title": "New Saved Filter", "title": "New Saved Filter",
"description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed. Once created, it will appear in a special namespace.", "description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed.",
"action": "Create new saved filter", "action": "Create new saved filter",
"titleRequired": "Please provide a title for the filter." "titleRequired": "Please provide a title for the filter."
}, },
@ -674,19 +615,13 @@
"updated": "Updated" "updated": "Updated"
}, },
"subscription": { "subscription": {
"subscribedProjectThroughParentNamespace": "You can't unsubscribe here because you are subscribed to this project through its namespace.",
"subscribedTaskThroughParentNamespace": "You can't unsubscribe here because you are subscribed to this task through its namespace.",
"subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.", "subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.",
"subscribedNamespace": "You are currently subscribed to this namespace and will receive notifications for changes.",
"notSubscribedNamespace": "You are not subscribed to this namespace and won't receive notifications for changes.",
"subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.", "subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.",
"notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.", "notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.",
"subscribedTask": "You are currently subscribed to this task and will receive notifications for changes.", "subscribedTask": "You are currently subscribed to this task and will receive notifications for changes.",
"notSubscribedTask": "You are not subscribed to this task and won't receive notifications for changes.", "notSubscribedTask": "You are not subscribed to this task and won't receive notifications for changes.",
"subscribe": "Subscribe", "subscribe": "Subscribe",
"unsubscribe": "Unsubscribe", "unsubscribe": "Unsubscribe",
"subscribeSuccessNamespace": "You are now subscribed to this namespace",
"unsubscribeSuccessNamespace": "You are now unsubscribed to this namespace",
"subscribeSuccessProject": "You are now subscribed to this project", "subscribeSuccessProject": "You are now subscribed to this project",
"unsubscribeSuccessProject": "You are now unsubscribed to this project", "unsubscribeSuccessProject": "You are now unsubscribed to this project",
"subscribeSuccessTask": "You are now subscribed to this task", "subscribeSuccessTask": "You are now subscribed to this task",
@ -763,7 +698,6 @@
"searchPlaceholder": "Type search for a new task to add as related…", "searchPlaceholder": "Type search for a new task to add as related…",
"createPlaceholder": "Add this as new related task", "createPlaceholder": "Add this as new related task",
"differentProject": "This task belongs to a different project.", "differentProject": "This task belongs to a different project.",
"differentNamespace": "This task belongs to a different namespace.",
"noneYet": "No task relations yet.", "noneYet": "No task relations yet.",
"delete": "Delete Task Relation", "delete": "Delete Task Relation",
"deleteText1": "Are you sure you want to delete this task relation?", "deleteText1": "Are you sure you want to delete this task relation?",
@ -848,19 +782,19 @@
"delete": { "delete": {
"header": "Delete the team", "header": "Delete the team",
"text1": "Are you sure you want to delete this team and all of its members?", "text1": "Are you sure you want to delete this team and all of its members?",
"text2": "All team members will lose access to projects and namespaces shared with this team. This CANNOT BE UNDONE!", "text2": "All team members will lose access to projects shared with this team. This CANNOT BE UNDONE!",
"success": "The team was successfully deleted." "success": "The team was successfully deleted."
}, },
"deleteUser": { "deleteUser": {
"header": "Remove a user from the team", "header": "Remove a user from the team",
"text1": "Are you sure you want to remove this user from the team?", "text1": "Are you sure you want to remove this user from the team?",
"text2": "They will lose access to all projects and namespaces this team has access to. This CANNOT BE UNDONE!", "text2": "They will lose access to all projects this team has access to. This CANNOT BE UNDONE!",
"success": "The user was successfully deleted from the team." "success": "The user was successfully deleted from the team."
}, },
"leave": { "leave": {
"title": "Leave team", "title": "Leave team",
"text1": "Are you sure you want to leave this team?", "text1": "Are you sure you want to leave this team?",
"text2": "You will lose access to all projects and namespaces this team has access to. If you change your mind you'll need a team admin to add you again.", "text2": "You will lose access to all projects this team has access to. If you change your mind you'll need a team admin to add you again.",
"success": "You have successfully left the team." "success": "You have successfully left the team."
} }
}, },
@ -894,7 +828,10 @@
"color": "Change the color of this task", "color": "Change the color of this task",
"move": "Move this task to another project", "move": "Move this task to another project",
"reminder": "Manage reminders of this task", "reminder": "Manage reminders of this task",
"description": "Toggle editing of the task description" "description": "Toggle editing of the task description",
"delete": "Delete this task",
"priority": "Change the priority of this task",
"favorite": "Mark this task as favorite / unfavorite"
}, },
"project": { "project": {
"title": "Project Views", "title": "Project Views",
@ -907,9 +844,9 @@
"title": "Navigation", "title": "Navigation",
"overview": "Navigate to overview", "overview": "Navigate to overview",
"upcoming": "Navigate to upcoming tasks", "upcoming": "Navigate to upcoming tasks",
"namespaces": "Navigate to namespaces & projects",
"labels": "Navigate to labels", "labels": "Navigate to labels",
"teams": "Navigate to teams" "teams": "Navigate to teams",
"projects": "Navigate to projects"
} }
}, },
"update": { "update": {
@ -924,7 +861,8 @@
"unarchive": "Un-Archive", "unarchive": "Un-Archive",
"setBackground": "Set background", "setBackground": "Set background",
"share": "Share", "share": "Share",
"newProject": "New project" "newProject": "New project",
"createProject": "Create project"
}, },
"apiConfig": { "apiConfig": {
"url": "Vikunja URL", "url": "Vikunja URL",
@ -943,7 +881,7 @@
"notification": { "notification": {
"title": "Notifications", "title": "Notifications",
"none": "You don't have any notifications. Have a nice day!", "none": "You don't have any notifications. Have a nice day!",
"explainer": "Notifications will appear here when actions on namespaces, projects or tasks you subscribed to happen." "explainer": "Notifications will appear here when actions projects or tasks you subscribed to happen."
}, },
"quickActions": { "quickActions": {
"commands": "Commands", "commands": "Commands",
@ -954,14 +892,12 @@
"teams": "Teams", "teams": "Teams",
"newProject": "Enter the title of the new project…", "newProject": "Enter the title of the new project…",
"newTask": "Enter the title of the new task…", "newTask": "Enter the title of the new task…",
"newNamespace": "Enter the title of the new namespace…",
"newTeam": "Enter the name of the new team…", "newTeam": "Enter the name of the new team…",
"createTask": "Create a task in the current project ({title})", "createTask": "Create a task in the current project ({title})",
"createProject": "Create a project in the current namespace ({title})", "createProject": "Create a project",
"cmds": { "cmds": {
"newTask": "New task", "newTask": "New task",
"newProject": "New project", "newProject": "New project",
"newNamespace": "New namespace",
"newTeam": "New team" "newTeam": "New team"
} }
}, },
@ -1017,16 +953,9 @@
"4017": "Invalid task filter comparator.", "4017": "Invalid task filter comparator.",
"4018": "Invalid task filter concatenator.", "4018": "Invalid task filter concatenator.",
"4019": "Invalid task filter value.", "4019": "Invalid task filter value.",
"5001": "The namespace does not exist.",
"5003": "You do not have access to the specified namespace.",
"5006": "The namespace name cannot be empty.",
"5009": "You need to have namespace read access to perform that action.",
"5010": "This team does not have access to that namespace.",
"5011": "This user has already access to that namespace.",
"5012": "The namespace is archived and can therefore only be accessed read only.",
"6001": "The team name cannot be empty.", "6001": "The team name cannot be empty.",
"6002": "The team does not exist.", "6002": "The team does not exist.",
"6004": "The team already has access to that namespace or project.", "6004": "The team already has access to that project.",
"6005": "The user is already a member of that team.", "6005": "The user is already a member of that team.",
"6006": "Cannot delete the last team member.", "6006": "Cannot delete the last team member.",
"6007": "The team does not have access to the project to perform that action.", "6007": "The team does not have access to the project to perform that action.",
@ -1053,4 +982,4 @@
"frontendVersion": "Frontend Version: {version}", "frontendVersion": "Frontend Version: {version}",
"apiVersion": "API Version: {version}" "apiVersion": "API Version: {version}"
} }
} }

View File

@ -6,9 +6,7 @@
"welcomeEvening": "Good Evening {username}!", "welcomeEvening": "Good Evening {username}!",
"lastViewed": "Last viewed", "lastViewed": "Last viewed",
"project": { "project": {
"newText": "You can create a new project for your new tasks:", "importText": "Import your projects and tasks from other services into Vikunja:",
"new": "New project",
"importText": "Or import your projects and tasks from other services into Vikunja:",
"import": "Import your data into Vikunja" "import": "Import your data into Vikunja"
} }
}, },
@ -143,7 +141,7 @@
}, },
"deletion": { "deletion": {
"title": "Delete your Vikunja Account", "title": "Delete your Vikunja Account",
"text1": "The deletion of your account is permanent and cannot be undone. We will delete all your namespaces, projects, tasks and everything associated with it.", "text1": "The deletion of your account is permanent and cannot be undone. We will delete all your projects, tasks and everything associated with it.",
"text2": "To proceed, please enter your password. You will receive an email with further instructions.", "text2": "To proceed, please enter your password. You will receive an email with further instructions.",
"confirm": "Delete my account", "confirm": "Delete my account",
"requestSuccess": "The request was successful. You'll receive an email with further instructions.", "requestSuccess": "The request was successful. You'll receive an email with further instructions.",
@ -157,7 +155,7 @@
}, },
"export": { "export": {
"title": "Export your Vikunja data", "title": "Export your Vikunja data",
"description": "You can request a copy of all your Vikunja data. This include Namespaces, Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.", "description": "You can request a copy of all your Vikunja data. This includes Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
"descriptionPasswordRequired": "Please enter your password to proceed:", "descriptionPasswordRequired": "Please enter your password to proceed:",
"request": "Request a copy of my Vikunja Data", "request": "Request a copy of my Vikunja Data",
"success": "You've successfully requested your Vikunja Data! We will send you an email once it's ready to download.", "success": "You've successfully requested your Vikunja Data! We will send you an email once it's ready to download.",
@ -165,14 +163,18 @@
} }
}, },
"project": { "project": {
"archived": "This project is archived. It is not possible to create new or edit tasks for it.", "archivedMessage": "This project is archived. It is not possible to create new or edit tasks for it.",
"archived": "Archived",
"showArchived": "Show Archived",
"title": "Project Title", "title": "Project Title",
"color": "Color", "color": "Color",
"projects": "Projects", "projects": "Projects",
"parent": "Parent Project",
"search": "Type to search for a project…", "search": "Type to search for a project…",
"searchSelect": "Click or press enter to select this project", "searchSelect": "Click or press enter to select this project",
"shared": "Shared Projects", "shared": "Shared Projects",
"noDescriptionAvailable": "No project description is available.", "noDescriptionAvailable": "No project description is available.",
"inboxTitle": "Inbox",
"create": { "create": {
"header": "New project", "header": "New project",
"titlePlaceholder": "The project's title goes here…", "titlePlaceholder": "The project's title goes here…",
@ -210,7 +212,7 @@
"duplicate": { "duplicate": {
"title": "Duplicate this project", "title": "Duplicate this project",
"label": "Duplicate", "label": "Duplicate",
"text": "Select a namespace which should hold the duplicated project:", "text": "Select a parent project which should hold the duplicated project:",
"success": "The project was successfully duplicated." "success": "The project was successfully duplicated."
}, },
"edit": { "edit": {
@ -321,67 +323,6 @@
} }
} }
}, },
"namespace": {
"title": "Namespaces & Projects",
"namespace": "Namespace",
"showArchived": "Show Archived",
"noneAvailable": "You don't have any namespaces right now.",
"unarchive": "Un-Archive",
"archived": "Archived",
"noProjects": "This namespace does not contain any projects.",
"createProject": "Create a new project in this namespace.",
"namespaces": "Namespaces",
"search": "Type to search for a namespace…",
"create": {
"title": "New namespace",
"titleRequired": "Please specify a title.",
"explanation": "A namespace is a collection of projects you can share and use to organize your projects with. In fact, every project belongs to a namespace.",
"tooltip": "What's a namespace?",
"success": "The namespace was successfully created."
},
"archive": {
"titleArchive": "Archive \"{namespace}\"",
"titleUnarchive": "Un-Archive \"{namespace}\"",
"archiveText": "You won't be able to edit this namespace or create new projects until you un-archive it. This will also archive all projects in this namespace.",
"unarchiveText": "You will be able to create new projects or edit it.",
"success": "The namespace was successfully archived.",
"unarchiveSuccess": "The namespace was successfully un-archived.",
"description": "If a namespace is archived, you cannot create new projects or edit it."
},
"delete": {
"title": "Delete \"{namespace}\"",
"text1": "Are you sure you want to delete this namespace and all of its contents?",
"text2": "This includes all projects and tasks and CANNOT BE UNDONE!",
"success": "The namespace was successfully deleted."
},
"edit": {
"title": "Edit \"{namespace}\"",
"success": "The namespace was successfully updated."
},
"share": {
"title": "Share \"{namespace}\""
},
"attributes": {
"title": "Namespace Title",
"titlePlaceholder": "The namespace title goes here…",
"description": "Description",
"descriptionPlaceholder": "The namespaces description goes here…",
"color": "Color",
"archived": "Is Archived",
"isArchived": "This namespace is archived"
},
"pseudo": {
"sharedProjects": {
"title": "Shared Projects"
},
"favorites": {
"title": "Favorites"
},
"savedFilters": {
"title": "Filters"
}
}
},
"filters": { "filters": {
"title": "Filters", "title": "Filters",
"clear": "Clear Filters", "clear": "Clear Filters",
@ -403,7 +344,7 @@
}, },
"create": { "create": {
"title": "New Saved Filter", "title": "New Saved Filter",
"description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed. Once created, it will appear in a special namespace.", "description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed.",
"action": "Create new saved filter", "action": "Create new saved filter",
"titleRequired": "Please provide a title for the filter." "titleRequired": "Please provide a title for the filter."
}, },
@ -674,19 +615,13 @@
"updated": "Updated" "updated": "Updated"
}, },
"subscription": { "subscription": {
"subscribedProjectThroughParentNamespace": "You can't unsubscribe here because you are subscribed to this project through its namespace.",
"subscribedTaskThroughParentNamespace": "You can't unsubscribe here because you are subscribed to this task through its namespace.",
"subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.", "subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.",
"subscribedNamespace": "You are currently subscribed to this namespace and will receive notifications for changes.",
"notSubscribedNamespace": "You are not subscribed to this namespace and won't receive notifications for changes.",
"subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.", "subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.",
"notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.", "notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.",
"subscribedTask": "You are currently subscribed to this task and will receive notifications for changes.", "subscribedTask": "You are currently subscribed to this task and will receive notifications for changes.",
"notSubscribedTask": "You are not subscribed to this task and won't receive notifications for changes.", "notSubscribedTask": "You are not subscribed to this task and won't receive notifications for changes.",
"subscribe": "Subscribe", "subscribe": "Subscribe",
"unsubscribe": "Unsubscribe", "unsubscribe": "Unsubscribe",
"subscribeSuccessNamespace": "You are now subscribed to this namespace",
"unsubscribeSuccessNamespace": "You are now unsubscribed to this namespace",
"subscribeSuccessProject": "You are now subscribed to this project", "subscribeSuccessProject": "You are now subscribed to this project",
"unsubscribeSuccessProject": "You are now unsubscribed to this project", "unsubscribeSuccessProject": "You are now unsubscribed to this project",
"subscribeSuccessTask": "You are now subscribed to this task", "subscribeSuccessTask": "You are now subscribed to this task",
@ -763,7 +698,6 @@
"searchPlaceholder": "Type search for a new task to add as related…", "searchPlaceholder": "Type search for a new task to add as related…",
"createPlaceholder": "Add this as new related task", "createPlaceholder": "Add this as new related task",
"differentProject": "This task belongs to a different project.", "differentProject": "This task belongs to a different project.",
"differentNamespace": "This task belongs to a different namespace.",
"noneYet": "No task relations yet.", "noneYet": "No task relations yet.",
"delete": "Delete Task Relation", "delete": "Delete Task Relation",
"deleteText1": "Are you sure you want to delete this task relation?", "deleteText1": "Are you sure you want to delete this task relation?",
@ -848,19 +782,19 @@
"delete": { "delete": {
"header": "Delete the team", "header": "Delete the team",
"text1": "Are you sure you want to delete this team and all of its members?", "text1": "Are you sure you want to delete this team and all of its members?",
"text2": "All team members will lose access to projects and namespaces shared with this team. This CANNOT BE UNDONE!", "text2": "All team members will lose access to projects shared with this team. This CANNOT BE UNDONE!",
"success": "The team was successfully deleted." "success": "The team was successfully deleted."
}, },
"deleteUser": { "deleteUser": {
"header": "Remove a user from the team", "header": "Remove a user from the team",
"text1": "Are you sure you want to remove this user from the team?", "text1": "Are you sure you want to remove this user from the team?",
"text2": "They will lose access to all projects and namespaces this team has access to. This CANNOT BE UNDONE!", "text2": "They will lose access to all projects this team has access to. This CANNOT BE UNDONE!",
"success": "The user was successfully deleted from the team." "success": "The user was successfully deleted from the team."
}, },
"leave": { "leave": {
"title": "Leave team", "title": "Leave team",
"text1": "Are you sure you want to leave this team?", "text1": "Are you sure you want to leave this team?",
"text2": "You will lose access to all projects and namespaces this team has access to. If you change your mind you'll need a team admin to add you again.", "text2": "You will lose access to all projects this team has access to. If you change your mind you'll need a team admin to add you again.",
"success": "You have successfully left the team." "success": "You have successfully left the team."
} }
}, },
@ -894,7 +828,10 @@
"color": "Change the color of this task", "color": "Change the color of this task",
"move": "Move this task to another project", "move": "Move this task to another project",
"reminder": "Manage reminders of this task", "reminder": "Manage reminders of this task",
"description": "Toggle editing of the task description" "description": "Toggle editing of the task description",
"delete": "Delete this task",
"priority": "Change the priority of this task",
"favorite": "Mark this task as favorite / unfavorite"
}, },
"project": { "project": {
"title": "Project Views", "title": "Project Views",
@ -907,9 +844,9 @@
"title": "Navigation", "title": "Navigation",
"overview": "Navigate to overview", "overview": "Navigate to overview",
"upcoming": "Navigate to upcoming tasks", "upcoming": "Navigate to upcoming tasks",
"namespaces": "Navigate to namespaces & projects",
"labels": "Navigate to labels", "labels": "Navigate to labels",
"teams": "Navigate to teams" "teams": "Navigate to teams",
"projects": "Navigate to projects"
} }
}, },
"update": { "update": {
@ -924,7 +861,8 @@
"unarchive": "Un-Archive", "unarchive": "Un-Archive",
"setBackground": "Set background", "setBackground": "Set background",
"share": "Share", "share": "Share",
"newProject": "New project" "newProject": "New project",
"createProject": "Create project"
}, },
"apiConfig": { "apiConfig": {
"url": "Vikunja URL", "url": "Vikunja URL",
@ -943,7 +881,7 @@
"notification": { "notification": {
"title": "Notifications", "title": "Notifications",
"none": "You don't have any notifications. Have a nice day!", "none": "You don't have any notifications. Have a nice day!",
"explainer": "Notifications will appear here when actions on namespaces, projects or tasks you subscribed to happen." "explainer": "Notifications will appear here when actions projects or tasks you subscribed to happen."
}, },
"quickActions": { "quickActions": {
"commands": "Commands", "commands": "Commands",
@ -954,14 +892,12 @@
"teams": "Teams", "teams": "Teams",
"newProject": "Enter the title of the new project…", "newProject": "Enter the title of the new project…",
"newTask": "Enter the title of the new task…", "newTask": "Enter the title of the new task…",
"newNamespace": "Enter the title of the new namespace…",
"newTeam": "Enter the name of the new team…", "newTeam": "Enter the name of the new team…",
"createTask": "Create a task in the current project ({title})", "createTask": "Create a task in the current project ({title})",
"createProject": "Create a project in the current namespace ({title})", "createProject": "Create a project",
"cmds": { "cmds": {
"newTask": "New task", "newTask": "New task",
"newProject": "New project", "newProject": "New project",
"newNamespace": "New namespace",
"newTeam": "New team" "newTeam": "New team"
} }
}, },
@ -1017,16 +953,9 @@
"4017": "Invalid task filter comparator.", "4017": "Invalid task filter comparator.",
"4018": "Invalid task filter concatenator.", "4018": "Invalid task filter concatenator.",
"4019": "Invalid task filter value.", "4019": "Invalid task filter value.",
"5001": "The namespace does not exist.",
"5003": "You do not have access to the specified namespace.",
"5006": "The namespace name cannot be empty.",
"5009": "You need to have namespace read access to perform that action.",
"5010": "This team does not have access to that namespace.",
"5011": "This user has already access to that namespace.",
"5012": "The namespace is archived and can therefore only be accessed read only.",
"6001": "The team name cannot be empty.", "6001": "The team name cannot be empty.",
"6002": "The team does not exist.", "6002": "The team does not exist.",
"6004": "The team already has access to that namespace or project.", "6004": "The team already has access to that project.",
"6005": "The user is already a member of that team.", "6005": "The user is already a member of that team.",
"6006": "Cannot delete the last team member.", "6006": "Cannot delete the last team member.",
"6007": "The team does not have access to the project to perform that action.", "6007": "The team does not have access to the project to perform that action.",
@ -1053,4 +982,4 @@
"frontendVersion": "Frontend Version: {version}", "frontendVersion": "Frontend Version: {version}",
"apiVersion": "API Version: {version}" "apiVersion": "API Version: {version}"
} }
} }

View File

@ -6,9 +6,7 @@
"welcomeEvening": "Good Evening {username}!", "welcomeEvening": "Good Evening {username}!",
"lastViewed": "Last viewed", "lastViewed": "Last viewed",
"project": { "project": {
"newText": "You can create a new project for your new tasks:", "importText": "Import your projects and tasks from other services into Vikunja:",
"new": "New project",
"importText": "Or import your projects and tasks from other services into Vikunja:",
"import": "Import your data into Vikunja" "import": "Import your data into Vikunja"
} }
}, },
@ -143,7 +141,7 @@
}, },
"deletion": { "deletion": {
"title": "Delete your Vikunja Account", "title": "Delete your Vikunja Account",
"text1": "The deletion of your account is permanent and cannot be undone. We will delete all your namespaces, projects, tasks and everything associated with it.", "text1": "The deletion of your account is permanent and cannot be undone. We will delete all your projects, tasks and everything associated with it.",
"text2": "To proceed, please enter your password. You will receive an email with further instructions.", "text2": "To proceed, please enter your password. You will receive an email with further instructions.",
"confirm": "Delete my account", "confirm": "Delete my account",
"requestSuccess": "The request was successful. You'll receive an email with further instructions.", "requestSuccess": "The request was successful. You'll receive an email with further instructions.",
@ -157,7 +155,7 @@
}, },
"export": { "export": {
"title": "Export your Vikunja data", "title": "Export your Vikunja data",
"description": "You can request a copy of all your Vikunja data. This include Namespaces, Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.", "description": "You can request a copy of all your Vikunja data. This includes Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
"descriptionPasswordRequired": "Please enter your password to proceed:", "descriptionPasswordRequired": "Please enter your password to proceed:",
"request": "Request a copy of my Vikunja Data", "request": "Request a copy of my Vikunja Data",
"success": "You've successfully requested your Vikunja Data! We will send you an email once it's ready to download.", "success": "You've successfully requested your Vikunja Data! We will send you an email once it's ready to download.",
@ -165,14 +163,18 @@
} }
}, },
"project": { "project": {
"archived": "This project is archived. It is not possible to create new or edit tasks for it.", "archivedMessage": "This project is archived. It is not possible to create new or edit tasks for it.",
"archived": "Archived",
"showArchived": "Show Archived",
"title": "Project Title", "title": "Project Title",
"color": "Color", "color": "Color",
"projects": "Projects", "projects": "Projects",
"parent": "Parent Project",
"search": "Type to search for a project…", "search": "Type to search for a project…",
"searchSelect": "Click or press enter to select this project", "searchSelect": "Click or press enter to select this project",
"shared": "Shared Projects", "shared": "Shared Projects",
"noDescriptionAvailable": "No project description is available.", "noDescriptionAvailable": "No project description is available.",
"inboxTitle": "Inbox",
"create": { "create": {
"header": "New project", "header": "New project",
"titlePlaceholder": "The project's title goes here…", "titlePlaceholder": "The project's title goes here…",
@ -210,7 +212,7 @@
"duplicate": { "duplicate": {
"title": "Duplicate this project", "title": "Duplicate this project",
"label": "Duplicate", "label": "Duplicate",
"text": "Select a namespace which should hold the duplicated project:", "text": "Select a parent project which should hold the duplicated project:",
"success": "The project was successfully duplicated." "success": "The project was successfully duplicated."
}, },
"edit": { "edit": {
@ -321,67 +323,6 @@
} }
} }
}, },
"namespace": {
"title": "Namespaces & Projects",
"namespace": "Namespace",
"showArchived": "Show Archived",
"noneAvailable": "You don't have any namespaces right now.",
"unarchive": "Un-Archive",
"archived": "Archived",
"noProjects": "This namespace does not contain any projects.",
"createProject": "Create a new project in this namespace.",
"namespaces": "Namespaces",
"search": "Type to search for a namespace…",
"create": {
"title": "New namespace",
"titleRequired": "Please specify a title.",
"explanation": "A namespace is a collection of projects you can share and use to organize your projects with. In fact, every project belongs to a namespace.",
"tooltip": "What's a namespace?",
"success": "The namespace was successfully created."
},
"archive": {
"titleArchive": "Archive \"{namespace}\"",
"titleUnarchive": "Un-Archive \"{namespace}\"",
"archiveText": "You won't be able to edit this namespace or create new projects until you un-archive it. This will also archive all projects in this namespace.",
"unarchiveText": "You will be able to create new projects or edit it.",
"success": "The namespace was successfully archived.",
"unarchiveSuccess": "The namespace was successfully un-archived.",
"description": "If a namespace is archived, you cannot create new projects or edit it."
},
"delete": {
"title": "Delete \"{namespace}\"",
"text1": "Are you sure you want to delete this namespace and all of its contents?",
"text2": "This includes all projects and tasks and CANNOT BE UNDONE!",
"success": "The namespace was successfully deleted."
},
"edit": {
"title": "Edit \"{namespace}\"",
"success": "The namespace was successfully updated."
},
"share": {
"title": "Share \"{namespace}\""
},
"attributes": {
"title": "Namespace Title",
"titlePlaceholder": "The namespace title goes here…",
"description": "Description",
"descriptionPlaceholder": "The namespaces description goes here…",
"color": "Color",
"archived": "Is Archived",
"isArchived": "This namespace is archived"
},
"pseudo": {
"sharedProjects": {
"title": "Shared Projects"
},
"favorites": {
"title": "Favorites"
},
"savedFilters": {
"title": "Filters"
}
}
},
"filters": { "filters": {
"title": "Filters", "title": "Filters",
"clear": "Clear Filters", "clear": "Clear Filters",
@ -403,7 +344,7 @@
}, },
"create": { "create": {
"title": "New Saved Filter", "title": "New Saved Filter",
"description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed. Once created, it will appear in a special namespace.", "description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed.",
"action": "Create new saved filter", "action": "Create new saved filter",
"titleRequired": "Please provide a title for the filter." "titleRequired": "Please provide a title for the filter."
}, },
@ -674,19 +615,13 @@
"updated": "Updated" "updated": "Updated"
}, },
"subscription": { "subscription": {
"subscribedProjectThroughParentNamespace": "You can't unsubscribe here because you are subscribed to this project through its namespace.",
"subscribedTaskThroughParentNamespace": "You can't unsubscribe here because you are subscribed to this task through its namespace.",
"subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.", "subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.",
"subscribedNamespace": "You are currently subscribed to this namespace and will receive notifications for changes.",
"notSubscribedNamespace": "You are not subscribed to this namespace and won't receive notifications for changes.",
"subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.", "subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.",
"notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.", "notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.",
"subscribedTask": "You are currently subscribed to this task and will receive notifications for changes.", "subscribedTask": "You are currently subscribed to this task and will receive notifications for changes.",
"notSubscribedTask": "You are not subscribed to this task and won't receive notifications for changes.", "notSubscribedTask": "You are not subscribed to this task and won't receive notifications for changes.",
"subscribe": "Subscribe", "subscribe": "Subscribe",
"unsubscribe": "Unsubscribe", "unsubscribe": "Unsubscribe",
"subscribeSuccessNamespace": "You are now subscribed to this namespace",
"unsubscribeSuccessNamespace": "You are now unsubscribed to this namespace",
"subscribeSuccessProject": "You are now subscribed to this project", "subscribeSuccessProject": "You are now subscribed to this project",
"unsubscribeSuccessProject": "You are now unsubscribed to this project", "unsubscribeSuccessProject": "You are now unsubscribed to this project",
"subscribeSuccessTask": "You are now subscribed to this task", "subscribeSuccessTask": "You are now subscribed to this task",
@ -763,7 +698,6 @@
"searchPlaceholder": "Type search for a new task to add as related…", "searchPlaceholder": "Type search for a new task to add as related…",
"createPlaceholder": "Add this as new related task", "createPlaceholder": "Add this as new related task",
"differentProject": "This task belongs to a different project.", "differentProject": "This task belongs to a different project.",
"differentNamespace": "This task belongs to a different namespace.",
"noneYet": "No task relations yet.", "noneYet": "No task relations yet.",
"delete": "Delete Task Relation", "delete": "Delete Task Relation",
"deleteText1": "Are you sure you want to delete this task relation?", "deleteText1": "Are you sure you want to delete this task relation?",
@ -848,19 +782,19 @@
"delete": { "delete": {
"header": "Delete the team", "header": "Delete the team",
"text1": "Are you sure you want to delete this team and all of its members?", "text1": "Are you sure you want to delete this team and all of its members?",
"text2": "All team members will lose access to projects and namespaces shared with this team. This CANNOT BE UNDONE!", "text2": "All team members will lose access to projects shared with this team. This CANNOT BE UNDONE!",
"success": "The team was successfully deleted." "success": "The team was successfully deleted."
}, },
"deleteUser": { "deleteUser": {
"header": "Remove a user from the team", "header": "Remove a user from the team",
"text1": "Are you sure you want to remove this user from the team?", "text1": "Are you sure you want to remove this user from the team?",
"text2": "They will lose access to all projects and namespaces this team has access to. This CANNOT BE UNDONE!", "text2": "They will lose access to all projects this team has access to. This CANNOT BE UNDONE!",
"success": "The user was successfully deleted from the team." "success": "The user was successfully deleted from the team."
}, },
"leave": { "leave": {
"title": "Leave team", "title": "Leave team",
"text1": "Are you sure you want to leave this team?", "text1": "Are you sure you want to leave this team?",
"text2": "You will lose access to all projects and namespaces this team has access to. If you change your mind you'll need a team admin to add you again.", "text2": "You will lose access to all projects this team has access to. If you change your mind you'll need a team admin to add you again.",
"success": "You have successfully left the team." "success": "You have successfully left the team."
} }
}, },
@ -894,7 +828,10 @@
"color": "Change the color of this task", "color": "Change the color of this task",
"move": "Move this task to another project", "move": "Move this task to another project",
"reminder": "Manage reminders of this task", "reminder": "Manage reminders of this task",
"description": "Toggle editing of the task description" "description": "Toggle editing of the task description",
"delete": "Delete this task",
"priority": "Change the priority of this task",
"favorite": "Mark this task as favorite / unfavorite"
}, },
"project": { "project": {
"title": "Project Views", "title": "Project Views",
@ -907,9 +844,9 @@
"title": "Navigation", "title": "Navigation",
"overview": "Navigate to overview", "overview": "Navigate to overview",
"upcoming": "Navigate to upcoming tasks", "upcoming": "Navigate to upcoming tasks",
"namespaces": "Navigate to namespaces & projects",
"labels": "Navigate to labels", "labels": "Navigate to labels",
"teams": "Navigate to teams" "teams": "Navigate to teams",
"projects": "Navigate to projects"
} }
}, },
"update": { "update": {
@ -924,7 +861,8 @@
"unarchive": "Un-Archive", "unarchive": "Un-Archive",
"setBackground": "Set background", "setBackground": "Set background",
"share": "Share", "share": "Share",
"newProject": "New project" "newProject": "New project",
"createProject": "Create project"
}, },
"apiConfig": { "apiConfig": {
"url": "Vikunja URL", "url": "Vikunja URL",
@ -943,7 +881,7 @@
"notification": { "notification": {
"title": "Notifications", "title": "Notifications",
"none": "You don't have any notifications. Have a nice day!", "none": "You don't have any notifications. Have a nice day!",
"explainer": "Notifications will appear here when actions on namespaces, projects or tasks you subscribed to happen." "explainer": "Notifications will appear here when actions projects or tasks you subscribed to happen."
}, },
"quickActions": { "quickActions": {
"commands": "Commands", "commands": "Commands",
@ -954,14 +892,12 @@
"teams": "Teams", "teams": "Teams",
"newProject": "Enter the title of the new project…", "newProject": "Enter the title of the new project…",
"newTask": "Enter the title of the new task…", "newTask": "Enter the title of the new task…",
"newNamespace": "Enter the title of the new namespace…",
"newTeam": "Enter the name of the new team…", "newTeam": "Enter the name of the new team…",
"createTask": "Create a task in the current project ({title})", "createTask": "Create a task in the current project ({title})",
"createProject": "Create a project in the current namespace ({title})", "createProject": "Create a project",
"cmds": { "cmds": {
"newTask": "New task", "newTask": "New task",
"newProject": "New project", "newProject": "New project",
"newNamespace": "New namespace",
"newTeam": "New team" "newTeam": "New team"
} }
}, },
@ -1017,16 +953,9 @@
"4017": "Invalid task filter comparator.", "4017": "Invalid task filter comparator.",
"4018": "Invalid task filter concatenator.", "4018": "Invalid task filter concatenator.",
"4019": "Invalid task filter value.", "4019": "Invalid task filter value.",
"5001": "The namespace does not exist.",
"5003": "You do not have access to the specified namespace.",
"5006": "The namespace name cannot be empty.",
"5009": "You need to have namespace read access to perform that action.",
"5010": "This team does not have access to that namespace.",
"5011": "This user has already access to that namespace.",
"5012": "The namespace is archived and can therefore only be accessed read only.",
"6001": "The team name cannot be empty.", "6001": "The team name cannot be empty.",
"6002": "The team does not exist.", "6002": "The team does not exist.",
"6004": "The team already has access to that namespace or project.", "6004": "The team already has access to that project.",
"6005": "The user is already a member of that team.", "6005": "The user is already a member of that team.",
"6006": "Cannot delete the last team member.", "6006": "Cannot delete the last team member.",
"6007": "The team does not have access to the project to perform that action.", "6007": "The team does not have access to the project to perform that action.",
@ -1053,4 +982,4 @@
"frontendVersion": "Frontend Version: {version}", "frontendVersion": "Frontend Version: {version}",
"apiVersion": "API Version: {version}" "apiVersion": "API Version: {version}"
} }
} }

View File

@ -6,9 +6,7 @@
"welcomeEvening": "Good Evening {username}!", "welcomeEvening": "Good Evening {username}!",
"lastViewed": "Xem gần đây", "lastViewed": "Xem gần đây",
"project": { "project": {
"newText": "You can create a new project for your new tasks:", "importText": "Import your projects and tasks from other services into Vikunja:",
"new": "New project",
"importText": "Or import your projects and tasks from other services into Vikunja:",
"import": "Import your data into Vikunja" "import": "Import your data into Vikunja"
} }
}, },
@ -143,7 +141,7 @@
}, },
"deletion": { "deletion": {
"title": "Xóa tài khoản của bạn", "title": "Xóa tài khoản của bạn",
"text1": "The deletion of your account is permanent and cannot be undone. We will delete all your namespaces, projects, tasks and everything associated with it.", "text1": "The deletion of your account is permanent and cannot be undone. We will delete all your projects, tasks and everything associated with it.",
"text2": "Để tiếp tục, vui lòng nhập mật khẩu của bạn. Bạn sẽ nhận được một email hướng dẫn thêm.", "text2": "Để tiếp tục, vui lòng nhập mật khẩu của bạn. Bạn sẽ nhận được một email hướng dẫn thêm.",
"confirm": "Xóa tài khoản của tôi", "confirm": "Xóa tài khoản của tôi",
"requestSuccess": "Yêu cầu đã thành công. Bạn sẽ nhận được một email hướng dẫn thêm.", "requestSuccess": "Yêu cầu đã thành công. Bạn sẽ nhận được một email hướng dẫn thêm.",
@ -157,7 +155,7 @@
}, },
"export": { "export": {
"title": "Xuất dữ liệu Vikunja của bạn", "title": "Xuất dữ liệu Vikunja của bạn",
"description": "You can request a copy of all your Vikunja data. This include Namespaces, Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.", "description": "You can request a copy of all your Vikunja data. This includes Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
"descriptionPasswordRequired": "Vui lòng nhập mật khẩu của bạn để tiếp tục:", "descriptionPasswordRequired": "Vui lòng nhập mật khẩu của bạn để tiếp tục:",
"request": "Yêu cầu một bản sao Dữ liệu Vikunja của tôi", "request": "Yêu cầu một bản sao Dữ liệu Vikunja của tôi",
"success": "Bạn đã yêu cầu dữ liệu Vikunja của mình thành công! Chúng tôi sẽ gửi cho bạn một email sau khi nó sẵn sàng để tải xuống.", "success": "Bạn đã yêu cầu dữ liệu Vikunja của mình thành công! Chúng tôi sẽ gửi cho bạn một email sau khi nó sẵn sàng để tải xuống.",
@ -165,14 +163,18 @@
} }
}, },
"project": { "project": {
"archived": "This project is archived. It is not possible to create new or edit tasks for it.", "archivedMessage": "This project is archived. It is not possible to create new or edit tasks for it.",
"archived": "Archived",
"showArchived": "Show Archived",
"title": "Project Title", "title": "Project Title",
"color": "Color", "color": "Color",
"projects": "Projects", "projects": "Projects",
"parent": "Parent Project",
"search": "Type to search for a project…", "search": "Type to search for a project…",
"searchSelect": "Click or press enter to select this project", "searchSelect": "Click or press enter to select this project",
"shared": "Shared Projects", "shared": "Shared Projects",
"noDescriptionAvailable": "No project description is available.", "noDescriptionAvailable": "No project description is available.",
"inboxTitle": "Inbox",
"create": { "create": {
"header": "New project", "header": "New project",
"titlePlaceholder": "The project's title goes here…", "titlePlaceholder": "The project's title goes here…",
@ -210,7 +212,7 @@
"duplicate": { "duplicate": {
"title": "Duplicate this project", "title": "Duplicate this project",
"label": "Duplicate", "label": "Duplicate",
"text": "Select a namespace which should hold the duplicated project:", "text": "Select a parent project which should hold the duplicated project:",
"success": "The project was successfully duplicated." "success": "The project was successfully duplicated."
}, },
"edit": { "edit": {
@ -321,67 +323,6 @@
} }
} }
}, },
"namespace": {
"title": "Namespaces & Projects",
"namespace": "Góc làm việc",
"showArchived": "Hiển thị đã lưu trữ",
"noneAvailable": "Bạn không có bất kỳ góc làm việc nào.",
"unarchive": "Bỏ lưu trữ",
"archived": "Đã lưu trữ",
"noProjects": "This namespace does not contain any projects.",
"createProject": "Create a new project in this namespace.",
"namespaces": "Góc làm việc",
"search": "Gõ để tìm kiếm một góc làm việc…",
"create": {
"title": "Góc làm việc mới",
"titleRequired": "Hãy đặt một tiêu đề.",
"explanation": "A namespace is a collection of projects you can share and use to organize your projects with. In fact, every project belongs to a namespace.",
"tooltip": "Góc làm việc là gì?",
"success": "Góc làm việc đã được tạo."
},
"archive": {
"titleArchive": "Lưu trữ \"{namespace}\"",
"titleUnarchive": "Bỏ lưu trữ \"{namespace}\"",
"archiveText": "You won't be able to edit this namespace or create new projects until you un-archive it. This will also archive all projects in this namespace.",
"unarchiveText": "You will be able to create new projects or edit it.",
"success": "Góc làm việc đã lưu trữ thành công.",
"unarchiveSuccess": "Góc làm việc đã được bỏ lưu trữ thành công.",
"description": "If a namespace is archived, you cannot create new projects or edit it."
},
"delete": {
"title": "Xóa \"{namespace}\"",
"text1": "Bạn có chắc muốn loại bỏ góc làm việc này và tất cả nội dung của nó không?",
"text2": "This includes all projects and tasks and CANNOT BE UNDONE!",
"success": "Góc làm việc đã được loại bỏ."
},
"edit": {
"title": "Chỉnh sửa \"{namespace}\"",
"success": "Góc làm việc đã được làm mới."
},
"share": {
"title": "Chia sẻ \"{namespace}\""
},
"attributes": {
"title": "Tên Góc làm việc",
"titlePlaceholder": "Tên góc làm việc ở đây…",
"description": "Mô tả",
"descriptionPlaceholder": "Mô tả góc làm việc ở đây…",
"color": "Màu sắc",
"archived": "Được lưu trữ",
"isArchived": "Góc làm việc này đã được lưu trữ"
},
"pseudo": {
"sharedProjects": {
"title": "Shared Projects"
},
"favorites": {
"title": "Ưa thích"
},
"savedFilters": {
"title": "Bộ lọc"
}
}
},
"filters": { "filters": {
"title": "Bộ lọc", "title": "Bộ lọc",
"clear": "Xoá các bộ lọc", "clear": "Xoá các bộ lọc",
@ -403,7 +344,7 @@
}, },
"create": { "create": {
"title": "Bộ lọc đã lưu mới", "title": "Bộ lọc đã lưu mới",
"description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed. Once created, it will appear in a special namespace.", "description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed.",
"action": "Tạo thêm bộ lọc sẵn", "action": "Tạo thêm bộ lọc sẵn",
"titleRequired": "Please provide a title for the filter." "titleRequired": "Please provide a title for the filter."
}, },
@ -674,19 +615,13 @@
"updated": "Đã cập nhật" "updated": "Đã cập nhật"
}, },
"subscription": { "subscription": {
"subscribedProjectThroughParentNamespace": "You can't unsubscribe here because you are subscribed to this project through its namespace.",
"subscribedTaskThroughParentNamespace": "You can't unsubscribe here because you are subscribed to this task through its namespace.",
"subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.", "subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.",
"subscribedNamespace": "You are currently subscribed to this namespace and will receive notifications for changes.",
"notSubscribedNamespace": "You are not subscribed to this namespace and won't receive notifications for changes.",
"subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.", "subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.",
"notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.", "notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.",
"subscribedTask": "You are currently subscribed to this task and will receive notifications for changes.", "subscribedTask": "You are currently subscribed to this task and will receive notifications for changes.",
"notSubscribedTask": "You are not subscribed to this task and won't receive notifications for changes.", "notSubscribedTask": "You are not subscribed to this task and won't receive notifications for changes.",
"subscribe": "Theo dõi", "subscribe": "Theo dõi",
"unsubscribe": "Bỏ theo dõi", "unsubscribe": "Bỏ theo dõi",
"subscribeSuccessNamespace": "You are now subscribed to this namespace",
"unsubscribeSuccessNamespace": "You are now unsubscribed to this namespace",
"subscribeSuccessProject": "You are now subscribed to this project", "subscribeSuccessProject": "You are now subscribed to this project",
"unsubscribeSuccessProject": "You are now unsubscribed to this project", "unsubscribeSuccessProject": "You are now unsubscribed to this project",
"subscribeSuccessTask": "You are now subscribed to this task", "subscribeSuccessTask": "You are now subscribed to this task",
@ -763,7 +698,6 @@
"searchPlaceholder": "Gõ tìm kiếm một công việc để thêm dưới dạng liên quan…", "searchPlaceholder": "Gõ tìm kiếm một công việc để thêm dưới dạng liên quan…",
"createPlaceholder": "Thêm điều này làm công việc liên quan mới", "createPlaceholder": "Thêm điều này làm công việc liên quan mới",
"differentProject": "This task belongs to a different project.", "differentProject": "This task belongs to a different project.",
"differentNamespace": "Công việc này thuộc về một Góc làm việc khác.",
"noneYet": "Không có công việc liên quan nào.", "noneYet": "Không có công việc liên quan nào.",
"delete": "Xóa công việc liên quan", "delete": "Xóa công việc liên quan",
"deleteText1": "Bạn có chắc muốn xóa công việc liên quan này không?", "deleteText1": "Bạn có chắc muốn xóa công việc liên quan này không?",
@ -848,19 +782,19 @@
"delete": { "delete": {
"header": "Giải tán Team", "header": "Giải tán Team",
"text1": "Bạn có chắc giải tán Team này không?", "text1": "Bạn có chắc giải tán Team này không?",
"text2": "All team members will lose access to projects and namespaces shared with this team. This CANNOT BE UNDONE!", "text2": "All team members will lose access to projects shared with this team. This CANNOT BE UNDONE!",
"success": "Team đã giải tán." "success": "Team đã giải tán."
}, },
"deleteUser": { "deleteUser": {
"header": "Đưa thành viên ra khỏi Team", "header": "Đưa thành viên ra khỏi Team",
"text1": "Bạn có chắc muốn đưa thành viên này ra khỏi Team không?", "text1": "Bạn có chắc muốn đưa thành viên này ra khỏi Team không?",
"text2": "They will lose access to all projects and namespaces this team has access to. This CANNOT BE UNDONE!", "text2": "They will lose access to all projects this team has access to. This CANNOT BE UNDONE!",
"success": "Thành viên đã rời khỏi Team." "success": "Thành viên đã rời khỏi Team."
}, },
"leave": { "leave": {
"title": "Leave team", "title": "Leave team",
"text1": "Are you sure you want to leave this team?", "text1": "Are you sure you want to leave this team?",
"text2": "You will lose access to all projects and namespaces this team has access to. If you change your mind you'll need a team admin to add you again.", "text2": "You will lose access to all projects this team has access to. If you change your mind you'll need a team admin to add you again.",
"success": "You have successfully left the team." "success": "You have successfully left the team."
} }
}, },
@ -894,7 +828,10 @@
"color": "Thay đổi màu công việc này", "color": "Thay đổi màu công việc này",
"move": "Move this task to another project", "move": "Move this task to another project",
"reminder": "Manage reminders of this task", "reminder": "Manage reminders of this task",
"description": "Toggle editing of the task description" "description": "Toggle editing of the task description",
"delete": "Delete this task",
"priority": "Change the priority of this task",
"favorite": "Mark this task as favorite / unfavorite"
}, },
"project": { "project": {
"title": "Project Views", "title": "Project Views",
@ -907,9 +844,9 @@
"title": "Điều hướng", "title": "Điều hướng",
"overview": "Navigate to overview", "overview": "Navigate to overview",
"upcoming": "Navigate to upcoming tasks", "upcoming": "Navigate to upcoming tasks",
"namespaces": "Navigate to namespaces & projects",
"labels": "Điều hướng đến nhãn", "labels": "Điều hướng đến nhãn",
"teams": "Điều hướng đến Team" "teams": "Điều hướng đến Team",
"projects": "Navigate to projects"
} }
}, },
"update": { "update": {
@ -924,7 +861,8 @@
"unarchive": "Bỏ lưu trữ", "unarchive": "Bỏ lưu trữ",
"setBackground": "Cài hình nền", "setBackground": "Cài hình nền",
"share": "Chia sẻ", "share": "Chia sẻ",
"newProject": "New project" "newProject": "New project",
"createProject": "Create project"
}, },
"apiConfig": { "apiConfig": {
"url": "URL Vikunja", "url": "URL Vikunja",
@ -943,7 +881,7 @@
"notification": { "notification": {
"title": "Thông báo", "title": "Thông báo",
"none": "Bạn không có thông báo nào. Chúc một ngày tốt lành!", "none": "Bạn không có thông báo nào. Chúc một ngày tốt lành!",
"explainer": "Notifications will appear here when actions on namespaces, projects or tasks you subscribed to happen." "explainer": "Notifications will appear here when actions projects or tasks you subscribed to happen."
}, },
"quickActions": { "quickActions": {
"commands": "Các lệnh", "commands": "Các lệnh",
@ -954,14 +892,12 @@
"teams": "Team", "teams": "Team",
"newProject": "Enter the title of the new project…", "newProject": "Enter the title of the new project…",
"newTask": "Đặt tên cho tác vụ mới…", "newTask": "Đặt tên cho tác vụ mới…",
"newNamespace": "Nhập tên của Góc làm việc mới…",
"newTeam": "Đặt tên cho đội nhóm mới…", "newTeam": "Đặt tên cho đội nhóm mới…",
"createTask": "Create a task in the current project ({title})", "createTask": "Create a task in the current project ({title})",
"createProject": "Create a project in the current namespace ({title})", "createProject": "Create a project",
"cmds": { "cmds": {
"newTask": "Tác vụ mới", "newTask": "Tác vụ mới",
"newProject": "New project", "newProject": "New project",
"newNamespace": "Góc làm việc mới",
"newTeam": "Team mới" "newTeam": "Team mới"
} }
}, },
@ -1017,16 +953,9 @@
"4017": "Bộ so sánh bộ lọc công việc không hợp lệ.", "4017": "Bộ so sánh bộ lọc công việc không hợp lệ.",
"4018": "Bộ lọc kết hợp không hợp lệ.", "4018": "Bộ lọc kết hợp không hợp lệ.",
"4019": "Giá trị bộ lọc công việc không hợp lệ.", "4019": "Giá trị bộ lọc công việc không hợp lệ.",
"5001": "Góc làm việc không có nữa.",
"5003": "Bạn chưa được phép bước vào vào góc làm việc được chỉ định.",
"5006": "Góc làm việc cần có một cái tên.",
"5009": "Bạn cần có quyền đọc với góc làm việc để thực hiện hành động đó.",
"5010": "Team này không có quyền bước vào góc làm việc đó.",
"5011": "Người này đã có quyền bước vào góc làm việc đó.",
"5012": "Góc làm việc đã được lưu trữ nên chỉ có thể vào đó để đọc.",
"6001": "Tên của Team không được để trống.", "6001": "Tên của Team không được để trống.",
"6002": "Team không tồn tại.", "6002": "Team không tồn tại.",
"6004": "The team already has access to that namespace or project.", "6004": "The team already has access to that project.",
"6005": "Người này đã là thành viên của Team đó rồi.", "6005": "Người này đã là thành viên của Team đó rồi.",
"6006": "Không thể loại bỏ thành viên cuối cùng của Team.", "6006": "Không thể loại bỏ thành viên cuối cùng của Team.",
"6007": "The team does not have access to the project to perform that action.", "6007": "The team does not have access to the project to perform that action.",
@ -1053,4 +982,4 @@
"frontendVersion": "Phiên bản giao diện người dùng: {version}", "frontendVersion": "Phiên bản giao diện người dùng: {version}",
"apiVersion": "Phiên bản API: {version}" "apiVersion": "Phiên bản API: {version}"
} }
} }

View File

@ -894,7 +894,10 @@
"color": "更改此任务的颜色", "color": "更改此任务的颜色",
"move": "Move this task to another project", "move": "Move this task to another project",
"reminder": "管理此任务的提醒", "reminder": "管理此任务的提醒",
"description": "切换编辑时的任务描述" "description": "切换编辑时的任务描述",
"delete": "Delete this task",
"priority": "Change the priority of this task",
"favorite": "Mark this task as favorite / unfavorite"
}, },
"project": { "project": {
"title": "Project Views", "title": "Project Views",
@ -1053,4 +1056,4 @@
"frontendVersion": "前端版本:{version}", "frontendVersion": "前端版本:{version}",
"apiVersion": "API 版本:{version}" "apiVersion": "API 版本:{version}"
} }
} }

View File

@ -6,9 +6,7 @@
"welcomeEvening": "Good Evening {username}!", "welcomeEvening": "Good Evening {username}!",
"lastViewed": "Last viewed", "lastViewed": "Last viewed",
"project": { "project": {
"newText": "You can create a new project for your new tasks:", "importText": "Import your projects and tasks from other services into Vikunja:",
"new": "New project",
"importText": "Or import your projects and tasks from other services into Vikunja:",
"import": "Import your data into Vikunja" "import": "Import your data into Vikunja"
} }
}, },
@ -143,7 +141,7 @@
}, },
"deletion": { "deletion": {
"title": "Delete your Vikunja Account", "title": "Delete your Vikunja Account",
"text1": "The deletion of your account is permanent and cannot be undone. We will delete all your namespaces, projects, tasks and everything associated with it.", "text1": "The deletion of your account is permanent and cannot be undone. We will delete all your projects, tasks and everything associated with it.",
"text2": "To proceed, please enter your password. You will receive an email with further instructions.", "text2": "To proceed, please enter your password. You will receive an email with further instructions.",
"confirm": "Delete my account", "confirm": "Delete my account",
"requestSuccess": "The request was successful. You'll receive an email with further instructions.", "requestSuccess": "The request was successful. You'll receive an email with further instructions.",
@ -157,7 +155,7 @@
}, },
"export": { "export": {
"title": "Export your Vikunja data", "title": "Export your Vikunja data",
"description": "You can request a copy of all your Vikunja data. This include Namespaces, Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.", "description": "You can request a copy of all your Vikunja data. This includes Projects, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
"descriptionPasswordRequired": "Please enter your password to proceed:", "descriptionPasswordRequired": "Please enter your password to proceed:",
"request": "Request a copy of my Vikunja Data", "request": "Request a copy of my Vikunja Data",
"success": "You've successfully requested your Vikunja Data! We will send you an email once it's ready to download.", "success": "You've successfully requested your Vikunja Data! We will send you an email once it's ready to download.",
@ -165,14 +163,18 @@
} }
}, },
"project": { "project": {
"archived": "This project is archived. It is not possible to create new or edit tasks for it.", "archivedMessage": "This project is archived. It is not possible to create new or edit tasks for it.",
"archived": "Archived",
"showArchived": "Show Archived",
"title": "Project Title", "title": "Project Title",
"color": "Color", "color": "Color",
"projects": "Projects", "projects": "Projects",
"parent": "Parent Project",
"search": "Type to search for a project…", "search": "Type to search for a project…",
"searchSelect": "Click or press enter to select this project", "searchSelect": "Click or press enter to select this project",
"shared": "Shared Projects", "shared": "Shared Projects",
"noDescriptionAvailable": "No project description is available.", "noDescriptionAvailable": "No project description is available.",
"inboxTitle": "Inbox",
"create": { "create": {
"header": "New project", "header": "New project",
"titlePlaceholder": "The project's title goes here…", "titlePlaceholder": "The project's title goes here…",
@ -210,7 +212,7 @@
"duplicate": { "duplicate": {
"title": "Duplicate this project", "title": "Duplicate this project",
"label": "Duplicate", "label": "Duplicate",
"text": "Select a namespace which should hold the duplicated project:", "text": "Select a parent project which should hold the duplicated project:",
"success": "The project was successfully duplicated." "success": "The project was successfully duplicated."
}, },
"edit": { "edit": {
@ -321,67 +323,6 @@
} }
} }
}, },
"namespace": {
"title": "Namespaces & Projects",
"namespace": "Namespace",
"showArchived": "Show Archived",
"noneAvailable": "You don't have any namespaces right now.",
"unarchive": "Un-Archive",
"archived": "Archived",
"noProjects": "This namespace does not contain any projects.",
"createProject": "Create a new project in this namespace.",
"namespaces": "Namespaces",
"search": "Type to search for a namespace…",
"create": {
"title": "New namespace",
"titleRequired": "Please specify a title.",
"explanation": "A namespace is a collection of projects you can share and use to organize your projects with. In fact, every project belongs to a namespace.",
"tooltip": "What's a namespace?",
"success": "The namespace was successfully created."
},
"archive": {
"titleArchive": "Archive \"{namespace}\"",
"titleUnarchive": "Un-Archive \"{namespace}\"",
"archiveText": "You won't be able to edit this namespace or create new projects until you un-archive it. This will also archive all projects in this namespace.",
"unarchiveText": "You will be able to create new projects or edit it.",
"success": "The namespace was successfully archived.",
"unarchiveSuccess": "The namespace was successfully un-archived.",
"description": "If a namespace is archived, you cannot create new projects or edit it."
},
"delete": {
"title": "Delete \"{namespace}\"",
"text1": "Are you sure you want to delete this namespace and all of its contents?",
"text2": "This includes all projects and tasks and CANNOT BE UNDONE!",
"success": "The namespace was successfully deleted."
},
"edit": {
"title": "Edit \"{namespace}\"",
"success": "The namespace was successfully updated."
},
"share": {
"title": "Share \"{namespace}\""
},
"attributes": {
"title": "Namespace Title",
"titlePlaceholder": "The namespace title goes here…",
"description": "Description",
"descriptionPlaceholder": "The namespaces description goes here…",
"color": "Color",
"archived": "Is Archived",
"isArchived": "This namespace is archived"
},
"pseudo": {
"sharedProjects": {
"title": "Shared Projects"
},
"favorites": {
"title": "Favorites"
},
"savedFilters": {
"title": "Filters"
}
}
},
"filters": { "filters": {
"title": "Filters", "title": "Filters",
"clear": "Clear Filters", "clear": "Clear Filters",
@ -403,7 +344,7 @@
}, },
"create": { "create": {
"title": "New Saved Filter", "title": "New Saved Filter",
"description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed. Once created, it will appear in a special namespace.", "description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed.",
"action": "Create new saved filter", "action": "Create new saved filter",
"titleRequired": "Please provide a title for the filter." "titleRequired": "Please provide a title for the filter."
}, },
@ -674,19 +615,13 @@
"updated": "Updated" "updated": "Updated"
}, },
"subscription": { "subscription": {
"subscribedProjectThroughParentNamespace": "You can't unsubscribe here because you are subscribed to this project through its namespace.",
"subscribedTaskThroughParentNamespace": "You can't unsubscribe here because you are subscribed to this task through its namespace.",
"subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.", "subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.",
"subscribedNamespace": "You are currently subscribed to this namespace and will receive notifications for changes.",
"notSubscribedNamespace": "You are not subscribed to this namespace and won't receive notifications for changes.",
"subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.", "subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.",
"notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.", "notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.",
"subscribedTask": "You are currently subscribed to this task and will receive notifications for changes.", "subscribedTask": "You are currently subscribed to this task and will receive notifications for changes.",
"notSubscribedTask": "You are not subscribed to this task and won't receive notifications for changes.", "notSubscribedTask": "You are not subscribed to this task and won't receive notifications for changes.",
"subscribe": "Subscribe", "subscribe": "Subscribe",
"unsubscribe": "Unsubscribe", "unsubscribe": "Unsubscribe",
"subscribeSuccessNamespace": "You are now subscribed to this namespace",
"unsubscribeSuccessNamespace": "You are now unsubscribed to this namespace",
"subscribeSuccessProject": "You are now subscribed to this project", "subscribeSuccessProject": "You are now subscribed to this project",
"unsubscribeSuccessProject": "You are now unsubscribed to this project", "unsubscribeSuccessProject": "You are now unsubscribed to this project",
"subscribeSuccessTask": "You are now subscribed to this task", "subscribeSuccessTask": "You are now subscribed to this task",
@ -763,7 +698,6 @@
"searchPlaceholder": "Type search for a new task to add as related…", "searchPlaceholder": "Type search for a new task to add as related…",
"createPlaceholder": "Add this as new related task", "createPlaceholder": "Add this as new related task",
"differentProject": "This task belongs to a different project.", "differentProject": "This task belongs to a different project.",
"differentNamespace": "This task belongs to a different namespace.",
"noneYet": "No task relations yet.", "noneYet": "No task relations yet.",
"delete": "Delete Task Relation", "delete": "Delete Task Relation",
"deleteText1": "Are you sure you want to delete this task relation?", "deleteText1": "Are you sure you want to delete this task relation?",
@ -894,7 +828,10 @@
"color": "Change the color of this task", "color": "Change the color of this task",
"move": "Move this task to another project", "move": "Move this task to another project",
"reminder": "Manage reminders of this task", "reminder": "Manage reminders of this task",
"description": "Toggle editing of the task description" "description": "Toggle editing of the task description",
"delete": "Delete this task",
"priority": "Change the priority of this task",
"favorite": "Mark this task as favorite / unfavorite"
}, },
"project": { "project": {
"title": "Project Views", "title": "Project Views",
@ -907,9 +844,9 @@
"title": "Navigation", "title": "Navigation",
"overview": "Navigate to overview", "overview": "Navigate to overview",
"upcoming": "Navigate to upcoming tasks", "upcoming": "Navigate to upcoming tasks",
"namespaces": "Navigate to namespaces & projects",
"labels": "Navigate to labels", "labels": "Navigate to labels",
"teams": "Navigate to teams" "teams": "Navigate to teams",
"projects": ""
} }
}, },
"update": { "update": {
@ -924,7 +861,8 @@
"unarchive": "Un-Archive", "unarchive": "Un-Archive",
"setBackground": "Set background", "setBackground": "Set background",
"share": "Share", "share": "Share",
"newProject": "New project" "newProject": "New project",
"createProject": ""
}, },
"apiConfig": { "apiConfig": {
"url": "Vikunja URL", "url": "Vikunja URL",
@ -954,14 +892,12 @@
"teams": "Teams", "teams": "Teams",
"newProject": "Enter the title of the new project…", "newProject": "Enter the title of the new project…",
"newTask": "Enter the title of the new task…", "newTask": "Enter the title of the new task…",
"newNamespace": "Enter the title of the new namespace…",
"newTeam": "Enter the name of the new team…", "newTeam": "Enter the name of the new team…",
"createTask": "Create a task in the current project ({title})", "createTask": "Create a task in the current project ({title})",
"createProject": "Create a project in the current namespace ({title})", "createProject": "Create a project in the current namespace ({title})",
"cmds": { "cmds": {
"newTask": "New task", "newTask": "New task",
"newProject": "New project", "newProject": "New project",
"newNamespace": "New namespace",
"newTeam": "New team" "newTeam": "New team"
} }
}, },
@ -1017,13 +953,6 @@
"4017": "Invalid task filter comparator.", "4017": "Invalid task filter comparator.",
"4018": "Invalid task filter concatenator.", "4018": "Invalid task filter concatenator.",
"4019": "Invalid task filter value.", "4019": "Invalid task filter value.",
"5001": "The namespace does not exist.",
"5003": "You do not have access to the specified namespace.",
"5006": "The namespace name cannot be empty.",
"5009": "You need to have namespace read access to perform that action.",
"5010": "This team does not have access to that namespace.",
"5011": "This user has already access to that namespace.",
"5012": "The namespace is archived and can therefore only be accessed read only.",
"6001": "The team name cannot be empty.", "6001": "The team name cannot be empty.",
"6002": "The team does not exist.", "6002": "The team does not exist.",
"6004": "The team already has access to that namespace or project.", "6004": "The team already has access to that namespace or project.",
@ -1053,4 +982,4 @@
"frontendVersion": "Frontend Version: {version}", "frontendVersion": "Frontend Version: {version}",
"apiVersion": "API Version: {version}" "apiVersion": "API Version: {version}"
} }
} }

View File

@ -23,6 +23,7 @@ declare global {
API_URL: string; API_URL: string;
SENTRY_ENABLED: boolean; SENTRY_ENABLED: boolean;
SENTRY_DSN: string; SENTRY_DSN: string;
PROJECT_INFINITE_NESTING_ENABLED: boolean;
} }
} }

View File

@ -1,18 +0,0 @@
import type {IAbstract} from './IAbstract'
import type {IProject} from './IProject'
import type {IUser} from './IUser'
import type {ISubscription} from './ISubscription'
export interface INamespace extends IAbstract {
id: number
title: string
description: string
owner: IUser
projects: IProject[]
isArchived: boolean
hexColor: string
subscription: ISubscription
created: Date
updated: Date
}

View File

@ -2,7 +2,6 @@ import type {IAbstract} from './IAbstract'
import type {ITask} from './ITask' import type {ITask} from './ITask'
import type {IUser} from './IUser' import type {IUser} from './IUser'
import type {ISubscription} from './ISubscription' import type {ISubscription} from './ISubscription'
import type {INamespace} from './INamespace'
export interface IProject extends IAbstract { export interface IProject extends IAbstract {
@ -11,7 +10,6 @@ export interface IProject extends IAbstract {
description: string description: string
owner: IUser owner: IUser
tasks: ITask[] tasks: ITask[]
namespaceId: INamespace['id']
isArchived: boolean isArchived: boolean
hexColor: string hexColor: string
identifier: string identifier: string
@ -20,6 +18,7 @@ export interface IProject extends IAbstract {
subscription: ISubscription subscription: ISubscription
position: number position: number
backgroundBlurHash: string backgroundBlurHash: string
parentProjectId: number
created: Date created: Date
updated: Date updated: Date

View File

@ -1,9 +1,8 @@
import type {IAbstract} from './IAbstract' import type {IAbstract} from './IAbstract'
import type {IProject} from './IProject' import type {IProject} from './IProject'
import type {INamespace} from './INamespace'
export interface IProjectDuplicate extends IAbstract { export interface IProjectDuplicate extends IAbstract {
projectId: number projectId: number
namespaceId: INamespace['id']
project: IProject project: IProject
parentProjectId: IProject['id']
} }

View File

@ -1,6 +0,0 @@
import type {ITeamShareBase} from './ITeamShareBase'
import type {INamespace} from './INamespace'
export interface ITeamNamespace extends ITeamShareBase {
namespaceId: INamespace['id']
}

View File

@ -1,6 +0,0 @@
import type {IUserShareBase} from './IUserShareBase'
import type {INamespace} from './INamespace'
export interface IUserNamespace extends IUserShareBase {
namespaceId: INamespace['id']
}

View File

@ -1,45 +0,0 @@
import AbstractModel from './abstractModel'
import ProjectModel from './project'
import UserModel from './user'
import SubscriptionModel from '@/models/subscription'
import type {INamespace} from '@/modelTypes/INamespace'
import type {IUser} from '@/modelTypes/IUser'
import type {IProject} from '@/modelTypes/IProject'
import type {ISubscription} from '@/modelTypes/ISubscription'
export default class NamespaceModel extends AbstractModel<INamespace> implements INamespace {
id = 0
title = ''
description = ''
owner: IUser = UserModel
projects: IProject[] = []
isArchived = false
hexColor = ''
subscription: ISubscription = null
created: Date = null
updated: Date = null
constructor(data: Partial<INamespace> = {}) {
super()
this.assignData(data)
if (this.hexColor !== '' && this.hexColor.substring(0, 1) !== '#') {
this.hexColor = '#' + this.hexColor
}
this.projects = this.projects.map(l => {
return new ProjectModel(l)
})
this.owner = new UserModel(this.owner)
if(typeof this.subscription !== 'undefined' && this.subscription !== null) {
this.subscription = new SubscriptionModel(this.subscription)
}
this.created = new Date(this.created)
this.updated = new Date(this.updated)
}
}

View File

@ -6,7 +6,6 @@ import SubscriptionModel from '@/models/subscription'
import type {IProject} from '@/modelTypes/IProject' import type {IProject} from '@/modelTypes/IProject'
import type {IUser} from '@/modelTypes/IUser' import type {IUser} from '@/modelTypes/IUser'
import type {ITask} from '@/modelTypes/ITask' import type {ITask} from '@/modelTypes/ITask'
import type {INamespace} from '@/modelTypes/INamespace'
import type {ISubscription} from '@/modelTypes/ISubscription' import type {ISubscription} from '@/modelTypes/ISubscription'
export default class ProjectModel extends AbstractModel<IProject> implements IProject { export default class ProjectModel extends AbstractModel<IProject> implements IProject {
@ -15,7 +14,6 @@ export default class ProjectModel extends AbstractModel<IProject> implements IPr
description = '' description = ''
owner: IUser = UserModel owner: IUser = UserModel
tasks: ITask[] = [] tasks: ITask[] = []
namespaceId: INamespace['id'] = 0
isArchived = false isArchived = false
hexColor = '' hexColor = ''
identifier = '' identifier = ''
@ -24,6 +22,7 @@ export default class ProjectModel extends AbstractModel<IProject> implements IPr
subscription: ISubscription = null subscription: ISubscription = null
position = 0 position = 0
backgroundBlurHash = '' backgroundBlurHash = ''
parentProjectId = 0
created: Date = null created: Date = null
updated: Date = null updated: Date = null
@ -46,7 +45,7 @@ export default class ProjectModel extends AbstractModel<IProject> implements IPr
if (typeof this.subscription !== 'undefined' && this.subscription !== null) { if (typeof this.subscription !== 'undefined' && this.subscription !== null) {
this.subscription = new SubscriptionModel(this.subscription) this.subscription = new SubscriptionModel(this.subscription)
} }
this.created = new Date(this.created) this.created = new Date(this.created)
this.updated = new Date(this.updated) this.updated = new Date(this.updated)
} }

View File

@ -2,13 +2,12 @@ import AbstractModel from './abstractModel'
import ProjectModel from './project' import ProjectModel from './project'
import type {IProjectDuplicate} from '@/modelTypes/IProjectDuplicate' import type {IProjectDuplicate} from '@/modelTypes/IProjectDuplicate'
import type {INamespace} from '@/modelTypes/INamespace'
import type {IProject} from '@/modelTypes/IProject' import type {IProject} from '@/modelTypes/IProject'
export default class ProjectDuplicateModel extends AbstractModel<IProjectDuplicate> implements IProjectDuplicate { export default class ProjectDuplicateModel extends AbstractModel<IProjectDuplicate> implements IProjectDuplicate {
projectId = 0 projectId = 0
namespaceId: INamespace['id'] = 0
project: IProject = ProjectModel project: IProject = ProjectModel
parentProjectId = 0
constructor(data : Partial<IProjectDuplicate>) { constructor(data : Partial<IProjectDuplicate>) {
super() super()

View File

@ -23,11 +23,6 @@ import SubscriptionModel from './subscription'
export const TASK_DEFAULT_COLOR = '#1973ff' export const TASK_DEFAULT_COLOR = '#1973ff'
const SUPPORTS_TRIGGERED_NOTIFICATION = 'Notification' in window && 'showTrigger' in Notification.prototype
if (!SUPPORTS_TRIGGERED_NOTIFICATION) {
console.debug('This browser does not support triggered notifications')
}
export function getHexColor(hexColor: string): string { export function getHexColor(hexColor: string): string {
if (hexColor === '' || hexColor === '#') { if (hexColor === '' || hexColor === '#') {
return TASK_DEFAULT_COLOR return TASK_DEFAULT_COLOR
@ -122,12 +117,6 @@ export default class TaskModel extends AbstractModel<ITask> implements ITask {
this.reminderDates = this.reminderDates.map(d => new Date(d)) this.reminderDates = this.reminderDates.map(d => new Date(d))
// Cancel all scheduled notifications for this task to be sure to only have available notifications
this.cancelScheduledNotifications().then(() => {
// Every time we see a reminder, we schedule a notification for it
this.reminderDates.forEach(d => this.scheduleNotification(d))
})
if (this.hexColor !== '' && this.hexColor.substring(0, 1) !== '#') { if (this.hexColor !== '' && this.hexColor.substring(0, 1) !== '#') {
this.hexColor = '#' + this.hexColor this.hexColor = '#' + this.hexColor
} }
@ -169,83 +158,5 @@ export default class TaskModel extends AbstractModel<ITask> implements ITask {
getHexColor() { getHexColor() {
return getHexColor(this.hexColor) return getHexColor(this.hexColor)
} }
/////////////////
// Helper functions
///////////////
async cancelScheduledNotifications() {
if (!SUPPORTS_TRIGGERED_NOTIFICATION) {
return
}
if (typeof navigator.serviceWorker === 'undefined') {
console.debug('Service Worker not available')
return
}
const registration = await navigator.serviceWorker.getRegistration()
if (typeof registration === 'undefined') {
return
}
// Get all scheduled notifications for this task and cancel them
const scheduledNotifications = await registration.getNotifications({
tag: `vikunja-task-${this.id}`,
includeTriggered: true,
})
console.debug('Already scheduled notifications:', scheduledNotifications)
scheduledNotifications.forEach(n => n.close())
}
async scheduleNotification(date) {
if (typeof navigator.serviceWorker === 'undefined') {
console.debug('Service Worker not available')
return
}
if (date < new Date()) {
console.debug('Date is in the past, not scheduling a notification. Date is ', date)
return
}
if (!SUPPORTS_TRIGGERED_NOTIFICATION) {
return
}
const {state} = await navigator.permissions.request({name: 'notifications'})
if (state !== 'granted') {
console.debug('Notification permission not granted, not showing notifications')
return
}
const registration = await navigator.serviceWorker.getRegistration()
if (typeof registration === 'undefined') {
console.error('No service worker registration available')
return
}
// Register the actual notification
try {
registration.showNotification('Vikunja Reminder', {
tag: `vikunja-task-${this.id}`, // Group notifications by task id so we're only showing one notification per task
body: this.title,
// eslint-disable-next-line no-undef
showTrigger: new TimestampTrigger(date),
badge: '/images/icons/badge-monochrome.png',
icon: '/images/icons/android-chrome-512x512.png',
data: {taskId: this.id},
actions: [
{
action: 'show-task',
title: 'Show task',
},
],
})
console.debug('Notification scheduled for ' + date)
} catch (e) {
throw new Error('Error scheduling notification', e)
}
}
} }

View File

@ -1,13 +0,0 @@
import TeamShareBaseModel from './teamShareBase'
import type {ITeamNamespace} from '@/modelTypes/ITeamNamespace'
import type {INamespace} from '@/modelTypes/INamespace'
export default class TeamNamespaceModel extends TeamShareBaseModel implements ITeamNamespace {
namespaceId: INamespace['id'] = 0
constructor(data: Partial<ITeamNamespace>) {
super(data)
this.assignData(data)
}
}

View File

@ -6,7 +6,7 @@ import type {ITeam} from '@/modelTypes/ITeam'
/** /**
* This class is a base class for common team sharing model. * This class is a base class for common team sharing model.
* It is extended in a way so it can be used for namespaces as well for projects. * It is extended in a way, so it can be used for projects.
*/ */
export default class TeamShareBaseModel extends AbstractModel<ITeamShareBase> implements ITeamShareBase { export default class TeamShareBaseModel extends AbstractModel<ITeamShareBase> implements ITeamShareBase {
teamId: ITeam['id'] = 0 teamId: ITeam['id'] = 0

View File

@ -1,14 +0,0 @@
import UserShareBaseModel from './userShareBase'
import type {INamespace} from '@/modelTypes/INamespace'
import type {IUserNamespace} from '@/modelTypes/IUserNamespace'
// This class extends the user share model with a 'rights' parameter which is used in sharing
export default class UserNamespaceModel extends UserShareBaseModel implements IUserNamespace {
namespaceId: INamespace['id'] = 0
constructor(data: Partial<IUserNamespace>) {
super(data)
this.assignData(data)
}
}

View File

@ -22,7 +22,6 @@ const DataExportDownload = () => import('@/views/user/DataExportDownload.vue')
// Tasks // Tasks
import UpcomingTasksComponent from '@/views/tasks/ShowTasks.vue' import UpcomingTasksComponent from '@/views/tasks/ShowTasks.vue'
import LinkShareAuthComponent from '@/views/sharing/LinkSharingAuth.vue' import LinkShareAuthComponent from '@/views/sharing/LinkSharingAuth.vue'
const ListNamespaces = () => import('@/views/namespaces/ListNamespaces.vue')
const TaskDetailView = () => import('@/views/tasks/TaskDetailView.vue') const TaskDetailView = () => import('@/views/tasks/TaskDetailView.vue')
// Team Handling // Team Handling
@ -41,6 +40,7 @@ const ProjectKanban = () => import('@/views/project/ProjectKanban.vue')
const ProjectInfo = () => import('@/views/project/ProjectInfo.vue') const ProjectInfo = () => import('@/views/project/ProjectInfo.vue')
// Project Settings // Project Settings
const ListProjects = () => import('@/views/project/ListProjects.vue')
const ProjectSettingEdit = () => import('@/views/project/settings/edit.vue') const ProjectSettingEdit = () => import('@/views/project/settings/edit.vue')
const ProjectSettingBackground = () => import('@/views/project/settings/background.vue') const ProjectSettingBackground = () => import('@/views/project/settings/background.vue')
const ProjectSettingDuplicate = () => import('@/views/project/settings/duplicate.vue') const ProjectSettingDuplicate = () => import('@/views/project/settings/duplicate.vue')
@ -48,12 +48,6 @@ const ProjectSettingShare = () => import('@/views/project/settings/share.vue')
const ProjectSettingDelete = () => import('@/views/project/settings/delete.vue') const ProjectSettingDelete = () => import('@/views/project/settings/delete.vue')
const ProjectSettingArchive = () => import('@/views/project/settings/archive.vue') const ProjectSettingArchive = () => import('@/views/project/settings/archive.vue')
// Namespace Settings
const NamespaceSettingEdit = () => import('@/views/namespaces/settings/edit.vue')
const NamespaceSettingShare = () => import('@/views/namespaces/settings/share.vue')
const NamespaceSettingArchive = () => import('@/views/namespaces/settings/archive.vue')
const NamespaceSettingDelete = () => import('@/views/namespaces/settings/delete.vue')
// Saved Filters // Saved Filters
const FilterNew = () => import('@/views/filters/FilterNew.vue') const FilterNew = () => import('@/views/filters/FilterNew.vue')
const FilterEdit = () => import('@/views/filters/FilterEdit.vue') const FilterEdit = () => import('@/views/filters/FilterEdit.vue')
@ -74,9 +68,6 @@ const UserSettingsTOTPComponent = () => import('@/views/user/settings/TOTP.vue')
// Project Handling // Project Handling
const NewProjectComponent = () => import('@/views/project/NewProject.vue') const NewProjectComponent = () => import('@/views/project/NewProject.vue')
// Namespace Handling
const NewNamespaceComponent = () => import('@/views/namespaces/NewNamespace.vue')
const EditTeamComponent = () => import('@/views/teams/EditTeam.vue') const EditTeamComponent = () => import('@/views/teams/EditTeam.vue')
const NewTeamComponent = () => import('@/views/teams/NewTeam.vue') const NewTeamComponent = () => import('@/views/teams/NewTeam.vue')
@ -203,54 +194,6 @@ const router = createRouter({
name: 'link-share.auth', name: 'link-share.auth',
component: LinkShareAuthComponent, component: LinkShareAuthComponent,
}, },
{
path: '/namespaces',
name: 'namespaces.index',
component: ListNamespaces,
},
{
path: '/namespaces/new',
name: 'namespace.create',
component: NewNamespaceComponent,
meta: {
showAsModal: true,
},
},
{
path: '/namespaces/:id/settings/edit',
name: 'namespace.settings.edit',
component: NamespaceSettingEdit,
meta: {
showAsModal: true,
},
props: route => ({ namespaceId: Number(route.params.id as string) }),
},
{
path: '/namespaces/:namespaceId/settings/share',
name: 'namespace.settings.share',
component: NamespaceSettingShare,
meta: {
showAsModal: true,
},
},
{
path: '/namespaces/:id/settings/archive',
name: 'namespace.settings.archive',
component: NamespaceSettingArchive,
meta: {
showAsModal: true,
},
props: route => ({ namespaceId: parseInt(route.params.id as string) }),
},
{
path: '/namespaces/:id/settings/delete',
name: 'namespace.settings.delete',
component: NamespaceSettingDelete,
meta: {
showAsModal: true,
},
props: route => ({ namespaceId: Number(route.params.id as string) }),
},
{ {
path: '/tasks/:id', path: '/tasks/:id',
name: 'task.detail', name: 'task.detail',
@ -282,13 +225,27 @@ const router = createRouter({
}, },
}, },
{ {
path: '/projects/new/:namespaceId/', path: '/projects',
name: 'projects.index',
component: ListProjects,
},
{
path: '/projects/new',
name: 'project.create', name: 'project.create',
component: NewProjectComponent, component: NewProjectComponent,
meta: { meta: {
showAsModal: true, showAsModal: true,
}, },
}, },
{
path: '/projects/:parentProjectId/new',
name: 'project.createFromParent',
component: NewProjectComponent,
props: route => ({ parentProjectId: Number(route.params.parentProjectId as string) }),
meta: {
showAsModal: true,
},
},
{ {
path: '/projects/:projectId/settings/edit', path: '/projects/:projectId/settings/edit',
name: 'project.settings.edit', name: 'project.settings.edit',
@ -412,7 +369,7 @@ const router = createRouter({
saveProjectView(to.params.projectId, to.name) saveProjectView(to.params.projectId, to.name)
// Properly set the page title when a task popup is closed // Properly set the page title when a task popup is closed
const projectStore = useProjectStore() const projectStore = useProjectStore()
const projectFromStore = projectStore.getProjectById(Number(to.params.projectId)) const projectFromStore = projectStore.projects[Number(to.params.projectId)]
if(projectFromStore) { if(projectFromStore) {
setTitle(projectFromStore.title) setTitle(projectFromStore.title)
} }

View File

@ -1,30 +0,0 @@
import AbstractService from './abstractService'
import NamespaceModel from '../models/namespace'
import type {INamespace} from '@/modelTypes/INamespace'
import {colorFromHex} from '@/helpers/color/colorFromHex'
export default class NamespaceService extends AbstractService<INamespace> {
constructor() {
super({
create: '/namespaces',
get: '/namespaces/{id}',
getAll: '/namespaces',
update: '/namespaces/{id}',
delete: '/namespaces/{id}',
})
}
modelFactory(data) {
return new NamespaceModel(data)
}
beforeUpdate(namespace) {
namespace.hexColor = colorFromHex(namespace.hexColor)
return namespace
}
beforeCreate(namespace) {
namespace.hexColor = colorFromHex(namespace.hexColor)
return namespace
}
}

View File

@ -7,7 +7,7 @@ import {colorFromHex} from '@/helpers/color/colorFromHex'
export default class ProjectService extends AbstractService<IProject> { export default class ProjectService extends AbstractService<IProject> {
constructor() { constructor() {
super({ super({
create: '/namespaces/{namespaceId}/projects', create: '/projects',
get: '/projects/{id}', get: '/projects/{id}',
getAll: '/projects', getAll: '/projects',
update: '/projects/{id}', update: '/projects/{id}',

View File

@ -12,7 +12,7 @@ import AbstractService from '@/services/abstractService'
import SavedFilterModel from '@/models/savedFilter' import SavedFilterModel from '@/models/savedFilter'
import {useBaseStore} from '@/stores/base' import {useBaseStore} from '@/stores/base'
import {useNamespaceStore} from '@/stores/namespaces' import {useProjectStore} from '@/stores/projects'
import {objectToSnakeCase, objectToCamelCase} from '@/helpers/case' import {objectToSnakeCase, objectToCamelCase} from '@/helpers/case'
import {success} from '@/message' import {success} from '@/message'
@ -40,7 +40,7 @@ export function getSavedFilterIdFromProjectId(projectId: IProject['id']) {
} }
export function isSavedFilter(project: IProject) { export function isSavedFilter(project: IProject) {
return getSavedFilterIdFromProjectId(project.id) > 0 return getSavedFilterIdFromProjectId(project?.id) > 0
} }
export default class SavedFilterService extends AbstractService<ISavedFilter> { export default class SavedFilterService extends AbstractService<ISavedFilter> {
@ -81,7 +81,7 @@ export default class SavedFilterService extends AbstractService<ISavedFilter> {
export function useSavedFilter(projectId?: MaybeRef<IProject['id']>) { export function useSavedFilter(projectId?: MaybeRef<IProject['id']>) {
const router = useRouter() const router = useRouter()
const {t} = useI18n({useScope:'global'}) const {t} = useI18n({useScope:'global'})
const namespaceStore = useNamespaceStore() const projectStore = useProjectStore()
const filterService = shallowReactive(new SavedFilterService()) const filterService = shallowReactive(new SavedFilterService())
@ -110,13 +110,13 @@ export function useSavedFilter(projectId?: MaybeRef<IProject['id']>) {
async function createFilter() { async function createFilter() {
filter.value = await filterService.create(filter.value) filter.value = await filterService.create(filter.value)
await namespaceStore.loadNamespaces() await projectStore.loadProjects()
router.push({name: 'project.index', params: {projectId: getProjectId(filter.value)}}) router.push({name: 'project.index', params: {projectId: getProjectId(filter.value)}})
} }
async function saveFilter() { async function saveFilter() {
const response = await filterService.update(filter.value) const response = await filterService.update(filter.value)
await namespaceStore.loadNamespaces() await projectStore.loadProjects()
success({message: t('filters.edit.success')}) success({message: t('filters.edit.success')})
response.filters = objectToSnakeCase(response.filters) response.filters = objectToSnakeCase(response.filters)
filter.value = response filter.value = response
@ -129,9 +129,9 @@ export function useSavedFilter(projectId?: MaybeRef<IProject['id']>) {
async function deleteFilter() { async function deleteFilter() {
await filterService.delete(filter.value) await filterService.delete(filter.value)
await namespaceStore.loadNamespaces() await projectStore.loadProjects()
success({message: t('filters.delete.success')}) success({message: t('filters.delete.success')})
router.push({name: 'namespaces.index'}) router.push({name: 'projects.index'})
} }
const titleValid = ref(true) const titleValid = ref(true)

View File

@ -1,23 +0,0 @@
import AbstractService from './abstractService'
import TeamNamespaceModel from '@/models/teamNamespace'
import type {ITeamNamespace} from '@/modelTypes/ITeamNamespace'
import TeamModel from '@/models/team'
export default class TeamNamespaceService extends AbstractService<ITeamNamespace> {
constructor() {
super({
create: '/namespaces/{namespaceId}/teams',
getAll: '/namespaces/{namespaceId}/teams',
update: '/namespaces/{namespaceId}/teams/{teamId}',
delete: '/namespaces/{namespaceId}/teams/{teamId}',
})
}
modelFactory(data) {
return new TeamNamespaceModel(data)
}
modelGetAllFactory(data) {
return new TeamModel(data)
}
}

View File

@ -1,23 +0,0 @@
import AbstractService from './abstractService'
import UserNamespaceModel from '@/models/userNamespace'
import type {IUserNamespace} from '@/modelTypes/IUserNamespace'
import UserModel from '@/models/user'
export default class UserNamespaceService extends AbstractService<IUserNamespace> {
constructor() {
super({
create: '/namespaces/{namespaceId}/users',
getAll: '/namespaces/{namespaceId}/users',
update: '/namespaces/{namespaceId}/users/{userId}',
delete: '/namespaces/{namespaceId}/users/{userId}',
})
}
modelFactory(data) {
return new UserNamespaceModel(data)
}
modelGetAllFactory(data) {
return new UserModel(data)
}
}

View File

@ -2,7 +2,7 @@ import {computed, readonly, ref} from 'vue'
import {defineStore, acceptHMRUpdate} from 'pinia' import {defineStore, acceptHMRUpdate} from 'pinia'
import {HTTPFactory, AuthenticatedHTTPFactory} from '@/helpers/fetcher' import {HTTPFactory, AuthenticatedHTTPFactory} from '@/helpers/fetcher'
import {i18n, getCurrentLanguage, saveLanguage} from '@/i18n' import {i18n, getCurrentLanguage, saveLanguage, setLanguage} from '@/i18n'
import {objectToSnakeCase} from '@/helpers/case' import {objectToSnakeCase} from '@/helpers/case'
import UserModel, { getAvatarUrl, getDisplayName } from '@/models/user' import UserModel, { getAvatarUrl, getDisplayName } from '@/models/user'
import UserSettingsService from '@/services/userSettings' import UserSettingsService from '@/services/userSettings'
@ -250,6 +250,7 @@ export const useAuthStore = defineStore('auth', () => {
...(info.value?.exp && {exp: info.value?.exp}), ...(info.value?.exp && {exp: info.value?.exp}),
}) })
await setLanguage(newUser.settings.language)
setUser(newUser) setUser(newUser)
updateLastUserRefresh() updateLastUserRefresh()

View File

@ -81,7 +81,7 @@ export const useBaseStore = defineStore('base', () => {
async function handleSetCurrentProject( async function handleSetCurrentProject(
{project, forceUpdate = false}: {project: IProject | null, forceUpdate?: boolean}, {project, forceUpdate = false}: {project: IProject | null, forceUpdate?: boolean},
) { ) {
if (project === null) { if (project === null || typeof project === 'undefined') {
setCurrentProject({}) setCurrentProject({})
setBackground('') setBackground('')
setBlurHash('') setBlurHash('')

View File

@ -1,236 +0,0 @@
import {computed, readonly, ref} from 'vue'
import {defineStore, acceptHMRUpdate} from 'pinia'
import NamespaceService from '../services/namespace'
import {setModuleLoading} from '@/stores/helper'
import {createNewIndexer} from '@/indexes'
import type {INamespace} from '@/modelTypes/INamespace'
import type {IProject} from '@/modelTypes/IProject'
import {useProjectStore} from '@/stores/projects'
const {add, remove, search, update} = createNewIndexer('namespaces', ['title', 'description'])
export const useNamespaceStore = defineStore('namespace', () => {
const projectStore = useProjectStore()
const isLoading = ref(false)
// FIXME: should be object with id as key
const namespaces = ref<INamespace[]>([])
const getProjectAndNamespaceById = computed(() => (projectId: IProject['id'], ignorePseudoNamespaces = false) => {
for (const n in namespaces.value) {
if (ignorePseudoNamespaces && namespaces.value[n].id < 0) {
continue
}
for (const l in namespaces.value[n].projects) {
if (namespaces.value[n].projects[l].id === projectId) {
return {
project: namespaces.value[n].projects[l],
namespace: namespaces.value[n],
}
}
}
}
return null
})
const getNamespaceById = computed(() => (namespaceId: INamespace['id']) => {
return namespaces.value.find(({id}) => id == namespaceId) || null
})
const searchNamespace = computed(() => {
return (query: string) => (
search(query)
?.filter(value => value > 0)
.map(getNamespaceById.value)
.filter(n => n !== null)
|| []
)
})
function setIsLoading(newIsLoading: boolean) {
isLoading.value = newIsLoading
}
function setNamespaces(newNamespaces: INamespace[]) {
namespaces.value = newNamespaces
newNamespaces.forEach(n => {
add(n)
// Check for each project in that namespace if it has a subscription and set it if not
n.projects.forEach(l => {
if (l.subscription === null || l.subscription.entity !== 'project') {
l.subscription = n.subscription
}
})
})
}
function setNamespaceById(namespace: INamespace) {
const namespaceIndex = namespaces.value.findIndex(n => n.id === namespace.id)
if (namespaceIndex === -1) {
return
}
if (!namespace.projects || namespace.projects.length === 0) {
namespace.projects = namespaces.value[namespaceIndex].projects
}
// Check for each project in that namespace if it has a subscription and set it if not
namespace.projects.forEach(l => {
if (l.subscription === null || l.subscription.entity !== 'project') {
l.subscription = namespace.subscription
}
})
namespaces.value[namespaceIndex] = namespace
update(namespace)
}
function setProjectInNamespaceById(project: IProject) {
for (const n in namespaces.value) {
// We don't have the namespace id on the project which means we need to loop over all projects until we find it.
// FIXME: Not ideal at all - we should fix that at the api level.
if (namespaces.value[n].id === project.namespaceId) {
for (const l in namespaces.value[n].projects) {
if (namespaces.value[n].projects[l].id === project.id) {
const namespace = namespaces.value[n]
namespace.projects[l] = project
namespaces.value[n] = namespace
return
}
}
}
}
}
function addNamespace(namespace: INamespace) {
namespaces.value.push(namespace)
add(namespace)
}
function removeNamespaceById(namespaceId: INamespace['id']) {
for (const n in namespaces.value) {
if (namespaces.value[n].id === namespaceId) {
remove(namespaces.value[n])
namespaces.value.splice(n, 1)
return
}
}
}
function addProjectToNamespace(project: IProject) {
for (const n in namespaces.value) {
if (namespaces.value[n].id === project.namespaceId) {
namespaces.value[n].projects.push(project)
return
}
}
}
function removeProjectFromNamespaceById(project: IProject) {
for (const n in namespaces.value) {
// We don't have the namespace id on the project which means we need to loop over all projects until we find it.
// FIXME: Not ideal at all - we should fix that at the api level.
if (namespaces.value[n].id === project.namespaceId) {
for (const l in namespaces.value[n].projects) {
if (namespaces.value[n].projects[l].id === project.id) {
namespaces.value[n].projects.splice(l, 1)
return
}
}
}
}
}
async function loadNamespaces() {
const cancel = setModuleLoading(setIsLoading)
const namespaceService = new NamespaceService()
try {
// We always load all namespaces and filter them on the frontend
const namespaces = await namespaceService.getAll({}, {is_archived: true}) as INamespace[]
setNamespaces(namespaces)
// Put all projects in the project state
const projects = namespaces.flatMap(({projects}) => projects)
projectStore.setProjects(projects)
return namespaces
} finally {
cancel()
}
}
function loadNamespacesIfFavoritesDontExist() {
// The first or second namespace should be the one holding all favorites
if (namespaces.value[0].id === -2 || namespaces.value[1]?.id === -2) {
return
}
return loadNamespaces()
}
function removeFavoritesNamespaceIfEmpty() {
if (namespaces.value[0].id === -2 && namespaces.value[0].projects.length === 0) {
namespaces.value.splice(0, 1)
}
}
async function deleteNamespace(namespace: INamespace) {
const cancel = setModuleLoading(setIsLoading)
const namespaceService = new NamespaceService()
try {
const response = await namespaceService.delete(namespace)
removeNamespaceById(namespace.id)
return response
} finally {
cancel()
}
}
async function createNamespace(namespace: INamespace) {
const cancel = setModuleLoading(setIsLoading)
const namespaceService = new NamespaceService()
try {
const createdNamespace = await namespaceService.create(namespace)
addNamespace(createdNamespace)
return createdNamespace
} finally {
cancel()
}
}
return {
isLoading: readonly(isLoading),
namespaces: readonly(namespaces),
getProjectAndNamespaceById,
getNamespaceById,
searchNamespace,
setNamespaces,
setNamespaceById,
setProjectInNamespaceById,
addNamespace,
removeNamespaceById,
addProjectToNamespace,
removeProjectFromNamespaceById,
loadNamespaces,
loadNamespacesIfFavoritesDontExist,
removeFavoritesNamespaceIfEmpty,
deleteNamespace,
createNamespace,
}
})
// support hot reloading
if (import.meta.hot) {
import.meta.hot.accept(acceptHMRUpdate(useNamespaceStore, import.meta.hot))
}

View File

@ -1,12 +1,14 @@
import {watch, reactive, shallowReactive, unref, toRefs, readonly, ref, computed} from 'vue' import {watch, reactive, shallowReactive, unref, readonly, ref, computed} from 'vue'
import {acceptHMRUpdate, defineStore} from 'pinia' import {acceptHMRUpdate, defineStore} from 'pinia'
import {useI18n} from 'vue-i18n' import {useI18n} from 'vue-i18n'
import {useRouter} from 'vue-router'
import ProjectService from '@/services/project' import ProjectService from '@/services/project'
import ProjectDuplicateService from '@/services/projectDuplicateService'
import ProjectDuplicateModel from '@/models/projectDuplicateModel'
import {setModuleLoading} from '@/stores/helper' import {setModuleLoading} from '@/stores/helper'
import {removeProjectFromHistory} from '@/modules/projectHistory' import {removeProjectFromHistory} from '@/modules/projectHistory'
import {createNewIndexer} from '@/indexes' import {createNewIndexer} from '@/indexes'
import {useNamespaceStore} from './namespaces'
import type {IProject} from '@/modelTypes/IProject' import type {IProject} from '@/modelTypes/IProject'
@ -16,9 +18,7 @@ import ProjectModel from '@/models/project'
import {success} from '@/message' import {success} from '@/message'
import {useBaseStore} from '@/stores/base' import {useBaseStore} from '@/stores/base'
const {add, remove, search, update} = createNewIndexer('projects', ['title', 'description']) const {remove, search, update} = createNewIndexer('projects', ['title', 'description'])
const FavoriteProjectsNamespace = -2
export interface ProjectState { export interface ProjectState {
[id: IProject['id']]: IProject [id: IProject['id']]: IProject
@ -26,16 +26,22 @@ export interface ProjectState {
export const useProjectStore = defineStore('project', () => { export const useProjectStore = defineStore('project', () => {
const baseStore = useBaseStore() const baseStore = useBaseStore()
const namespaceStore = useNamespaceStore() const router = useRouter()
const isLoading = ref(false) const isLoading = ref(false)
// The projects are stored as an object which has the project ids as keys. // The projects are stored as an object which has the project ids as keys.
const projects = ref<ProjectState>({}) const projects = ref<ProjectState>({})
const projectsArray = computed(() => Object.values(projects.value)
.sort((a, b) => a.position - b.position))
const notArchivedRootProjects = computed(() => projectsArray.value
.filter(p => p.parentProjectId === 0 && !p.isArchived))
const favoriteProjects = computed(() => projectsArray.value
.filter(p => !p.isArchived && p.isFavorite))
const hasProjects = computed(() => projectsArray.value.length > 0)
const getChildProjects = computed(() => {
const getProjectById = computed(() => { return (id: IProject['id']) => projectsArray.value.filter(p => p.parentProjectId === id)
return (id: IProject['id']) => typeof projects.value[id] !== 'undefined' ? projects.value[id] : null
}) })
const findProjectByExactname = computed(() => { const findProjectByExactname = computed(() => {
@ -53,7 +59,7 @@ export const useProjectStore = defineStore('project', () => {
?.filter(value => value > 0) ?.filter(value => value > 0)
.map(id => projects.value[id]) .map(id => projects.value[id])
.filter(project => project.isArchived === includeArchived) .filter(project => project.isArchived === includeArchived)
|| [] || []
} }
}) })
@ -65,16 +71,15 @@ export const useProjectStore = defineStore('project', () => {
projects.value[project.id] = project projects.value[project.id] = project
update(project) update(project)
// FIXME: This should be a watcher, but using a watcher instead will sometimes crash browser processes.
// Reverted from 31b7c1f217532bf388ba95a03f469508bee46f6a
if (baseStore.currentProject?.id === project.id) { if (baseStore.currentProject?.id === project.id) {
baseStore.setCurrentProject(project) baseStore.setCurrentProject(project)
} }
} }
function setProjects(newProjects: IProject[]) { function setProjects(newProjects: IProject[]) {
newProjects.forEach(l => { newProjects.forEach(p => setProject(p))
projects.value[l.id] = l
add(l)
})
} }
function removeProjectById(project: IProject) { function removeProjectById(project: IProject) {
@ -100,9 +105,11 @@ export const useProjectStore = defineStore('project', () => {
try { try {
const createdProject = await projectService.create(project) const createdProject = await projectService.create(project)
createdProject.namespaceId = project.namespaceId
namespaceStore.addProjectToNamespace(createdProject)
setProject(createdProject) setProject(createdProject)
router.push({
name: 'project.index',
params: { projectId: createdProject.id },
})
return createdProject return createdProject
} finally { } finally {
cancel() cancel()
@ -112,26 +119,14 @@ export const useProjectStore = defineStore('project', () => {
async function updateProject(project: IProject) { async function updateProject(project: IProject) {
const cancel = setModuleLoading(setIsLoading) const cancel = setModuleLoading(setIsLoading)
const projectService = new ProjectService() const projectService = new ProjectService()
try { try {
await projectService.update(project) const updatedProject = await projectService.update(project)
setProject(project) setProject(project)
namespaceStore.setProjectInNamespaceById(project)
// the returned project from projectService.update is the same! // the returned project from projectService.update is the same!
// in order to not create a manipulation in pinia store we have to create a new copy // in order to not create a manipulation in pinia store we have to create a new copy
const newProject = { return updatedProject
...project,
namespaceId: FavoriteProjectsNamespace,
}
namespaceStore.removeProjectFromNamespaceById(newProject)
if (project.isFavorite) {
namespaceStore.addProjectToNamespace(newProject)
}
namespaceStore.loadNamespacesIfFavoritesDontExist()
namespaceStore.removeFavoritesNamespaceIfEmpty()
return newProject
} catch (e) { } catch (e) {
// Reset the project state to the initial one to avoid confusion for the user // Reset the project state to the initial one to avoid confusion for the user
setProject({ setProject({
@ -151,7 +146,6 @@ export const useProjectStore = defineStore('project', () => {
try { try {
const response = await projectService.delete(project) const response = await projectService.delete(project)
removeProjectById(project) removeProjectById(project)
namespaceStore.removeProjectFromNamespaceById(project)
removeProjectFromHistory({id: project.id}) removeProjectFromHistory({id: project.id})
return response return response
} finally { } finally {
@ -159,11 +153,42 @@ export const useProjectStore = defineStore('project', () => {
} }
} }
async function loadProjects() {
const cancel = setModuleLoading(setIsLoading)
const projectService = new ProjectService()
try {
const loadedProjects = await projectService.getAll({}, {is_archived: true}) as IProject[]
projects.value = {}
setProjects(loadedProjects)
return loadedProjects
} finally {
cancel()
}
}
function getAncestors(project: IProject): IProject[] {
if (!project?.parentProjectId) {
return [project]
}
const parentProject = projects.value[project.parentProjectId]
return [
...getAncestors(parentProject),
project,
]
}
return { return {
isLoading: readonly(isLoading), isLoading: readonly(isLoading),
projects: readonly(projects), projects: readonly(projects),
projectsArray: readonly(projectsArray),
notArchivedRootProjects: readonly(notArchivedRootProjects),
favoriteProjects: readonly(favoriteProjects),
hasProjects: readonly(hasProjects),
getProjectById, getChildProjects,
findProjectByExactname, findProjectByExactname,
searchProject, searchProject,
@ -171,17 +196,24 @@ export const useProjectStore = defineStore('project', () => {
setProjects, setProjects,
removeProjectById, removeProjectById,
toggleProjectFavorite, toggleProjectFavorite,
loadProjects,
createProject, createProject,
updateProject, updateProject,
deleteProject, deleteProject,
getAncestors,
} }
}) })
export function useProject(projectId: MaybeRef<IProject['id']>) { export function useProject(projectId: MaybeRef<IProject['id']>) {
const projectService = shallowReactive(new ProjectService()) const projectService = shallowReactive(new ProjectService())
const {loading: isLoading} = toRefs(projectService) const projectDuplicateService = shallowReactive(new ProjectDuplicateService())
const isLoading = computed(() => projectService.loading || projectDuplicateService.loading)
const project: IProject = reactive(new ProjectModel()) const project: IProject = reactive(new ProjectModel())
const {t} = useI18n({useScope: 'global'}) const {t} = useI18n({useScope: 'global'})
const router = useRouter()
const projectStore = useProjectStore()
watch( watch(
() => unref(projectId), () => unref(projectId),
@ -192,20 +224,34 @@ export function useProject(projectId: MaybeRef<IProject['id']>) {
{immediate: true}, {immediate: true},
) )
const projectStore = useProjectStore()
async function save() { async function save() {
await projectStore.updateProject(project) const updatedProject = await projectStore.updateProject(project)
Object.assign(project, updatedProject)
success({message: t('project.edit.success')}) success({message: t('project.edit.success')})
} }
async function duplicateProject(parentProjectId: IProject['id']) {
const projectDuplicate = new ProjectDuplicateModel({
projectId: unref(projectId),
parentProjectId,
})
const duplicate = await projectDuplicateService.create(projectDuplicate)
projectStore.setProject(duplicate.project)
success({message: t('project.duplicate.success')})
router.push({name: 'project.index', params: {projectId: duplicate.project.id}})
}
return { return {
isLoading: readonly(isLoading), isLoading: readonly(isLoading),
project, project,
save, save,
duplicateProject,
} }
} }
// support hot reloading // support hot reloading
if (import.meta.hot) { if (import.meta.hot) {
import.meta.hot.accept(acceptHMRUpdate(useProjectStore, import.meta.hot)) import.meta.hot.accept(acceptHMRUpdate(useProjectStore, import.meta.hot))
} }

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