diff --git a/.drone.yml b/.drone.yml index 72f4874ce..27e99bade 100644 --- a/.drone.yml +++ b/.drone.yml @@ -99,7 +99,7 @@ steps: - dependencies - name: test-frontend - image: cypress/browsers:node14.17.0-chrome91-ff89 + image: cypress/browsers:node16.5.0-chrome94-ff93 pull: true environment: CYPRESS_API_URL: http://api:3456/api/v1 diff --git a/cypress/integration/user/login.spec.js b/cypress/integration/user/login.spec.js index ce6086ce0..238ec77f4 100644 --- a/cypress/integration/user/login.spec.js +++ b/cypress/integration/user/login.spec.js @@ -8,7 +8,7 @@ const testAndAssertFailed = fixture => { cy.wait(5000) // It can take waaaayy too long to log the user in cy.url().should('include', '/') - cy.get('div.notification.is-danger').contains('Wrong username or password.') + cy.get('div.message.danger').contains('Wrong username or password.') } context('Login', () => { diff --git a/cypress/integration/user/registration.spec.js b/cypress/integration/user/registration.spec.js index fc1b0fbde..fd940aa7e 100644 --- a/cypress/integration/user/registration.spec.js +++ b/cypress/integration/user/registration.spec.js @@ -32,7 +32,7 @@ context('Registration', () => { cy.get('h2').should('contain', `Hi ${fixture.username}!`) }) - it('Should fail', () => { + it.only('Should fail', () => { const fixture = { username: 'test', password: '123456', @@ -45,6 +45,6 @@ context('Registration', () => { cy.get('#password').type(fixture.password) cy.get('#passwordValidation').type(fixture.password) cy.get('#register-submit').click() - cy.get('div.notification.is-danger').contains('A user with this username already exists.') + cy.get('div.message.danger').contains('A user with this username already exists.') }) }) \ No newline at end of file diff --git a/package.json b/package.json index 3439849aa..b73d36fa9 100644 --- a/package.json +++ b/package.json @@ -17,17 +17,17 @@ "browserslist:update": "npx browserslist@latest --update-db" }, "dependencies": { - "@bulvar/bulma": "^0.9.3", + "@bulvar/bulma": "^0.9.4", "@github/hotkey": "1.6.0", "@kyvg/vue3-notification": "2.3.4", "@sentry/tracing": "6.15.0", "@sentry/vue": "6.15.0", - "@vue/compat": "3.2.22", - "@vueuse/core": "7.0.1", + "@vue/compat": "3.2.23", + "@vueuse/core": "7.1.2", "camel-case": "4.1.2", "codemirror": "5.64.0", "copy-to-clipboard": "3.3.1", - "date-fns": "2.26.0", + "date-fns": "2.27.0", "dompurify": "2.3.3", "easymde": "2.15.0", "flatpickr": "4.6.9", @@ -36,57 +36,58 @@ "is-touch-device": "1.0.1", "lodash.clonedeep": "4.5.0", "lodash.debounce": "4.0.8", - "marked": "4.0.4", + "marked": "4.0.5", "register-service-worker": "1.7.2", "snake-case": "3.0.4", "ufo": "0.7.9", "v-tooltip": "4.0.0-beta.2", - "vue": "3.2.22", + "vue": "3.2.23", "vue-advanced-cropper": "2.7.0", "vue-drag-resize": "2.0.3", "vue-flatpickr-component": "9.0.5", - "vue-i18n": "9.2.0-beta.20", + "vue-i18n": "9.2.0-beta.22", "vue-router": "4.0.12", "vuedraggable": "4.1.0", "vuex": "4.0.2", "workbox-precaching": "6.4.1" }, "devDependencies": { - "@4tw/cypress-drag-drop": "2.0.0", + "@4tw/cypress-drag-drop": "2.1.0", "@fortawesome/fontawesome-svg-core": "1.2.36", "@fortawesome/free-regular-svg-icons": "5.15.4", "@fortawesome/free-solid-svg-icons": "5.15.4", "@fortawesome/vue-fontawesome": "3.0.0-5", "@types/flexsearch": "0.7.2", "@types/jest": "27.0.3", - "@typescript-eslint/eslint-plugin": "5.4.0", - "@typescript-eslint/parser": "5.4.0", + "@typescript-eslint/eslint-plugin": "5.5.0", + "@typescript-eslint/parser": "5.5.0", "@vitejs/plugin-legacy": "1.6.3", - "@vitejs/plugin-vue": "1.10.0", + "@vitejs/plugin-vue": "1.10.1", "@vue/eslint-config-typescript": "9.1.0", + "autoprefixer": "10.4.0", "axios": "0.24.0", "browserslist": "4.18.1", "cypress": "8.7.0", "cypress-file-upload": "5.0.8", - "esbuild": "0.13.15", + "esbuild": "0.14.1", "eslint": "8.3.0", "eslint-plugin-vue": "8.1.1", "express": "4.17.1", "faker": "5.5.3", - "jest": "27.3.1", - "netlify-cli": "7.1.0", - "postcss": "8.3.11", + "jest": "27.4.2", + "netlify-cli": "8.0.6", + "postcss": "8.4.4", "postcss-preset-env": "7.0.1", - "rollup": "2.60.1", + "rollup": "2.60.2", "rollup-plugin-visualizer": "5.5.2", - "sass": "1.43.4", + "sass": "1.44.0", "slugify": "1.6.3", "ts-jest": "27.0.7", "typescript": "4.5.2", "vite": "2.6.14", - "vite-plugin-pwa": "0.11.7", + "vite-plugin-pwa": "0.11.9", "vite-svg-loader": "3.1.0", - "vue-tsc": "0.29.6", + "vue-tsc": "0.29.8", "wait-on": "6.0.0", "workbox-cli": "6.4.1" }, @@ -95,7 +96,8 @@ "env": { "browser": true, "es2021": true, - "node": true + "node": true, + "vue/setup-compiler-macros": true }, "extends": [ "eslint:recommended", @@ -119,6 +121,7 @@ "error", "never" ], + "vue/script-setup-uses-vars": "error", "vue/multi-word-component-names": 0 }, "parser": "vue-eslint-parser", @@ -129,7 +132,10 @@ "ignorePatterns": [ "*.test.*", "cypress/*" - ] + ], + "globals": { + "defineProps": "readonly" + } }, "postcss": { "plugins": { @@ -154,5 +160,6 @@ "json" ] }, - "license": "AGPL-3.0-or-later" -} + "license": "AGPL-3.0-or-later", + "packageManager": "yarn@1.22.17" +} \ No newline at end of file diff --git a/src/components/home/contentAuth.vue b/src/components/home/contentAuth.vue index 7a2bd2427..016ba078b 100644 --- a/src/components/home/contentAuth.vue +++ b/src/components/home/contentAuth.vue @@ -82,7 +82,7 @@ export default { this.$route.name === 'labels.index' || this.$route.name === 'migrate.start' || this.$route.name === 'migrate.wunderlist' || - this.$route.name === 'user.settings' || + this.$route.name.startsWith('user.settings') || this.$route.name === 'namespaces.index' ) { return this.$store.dispatch(CURRENT_LIST, null) diff --git a/src/components/misc/api-config.vue b/src/components/misc/api-config.vue index 07ca857b8..c0e542f3a 100644 --- a/src/components/misc/api-config.vue +++ b/src/components/misc/api-config.vue @@ -30,27 +30,25 @@ {{ $t('apiConfig.change') }} -
+ {{ successMsg }} -
-
+ + {{ errorMsg }} -
+ + + diff --git a/src/components/misc/no-auth-wrapper.vue b/src/components/misc/no-auth-wrapper.vue index 22832fe94..3dfc7f5e8 100644 --- a/src/components/misc/no-auth-wrapper.vue +++ b/src/components/misc/no-auth-wrapper.vue @@ -2,14 +2,9 @@
@@ -17,6 +12,7 @@ diff --git a/src/components/tasks/gantt-component.vue b/src/components/tasks/gantt-component.vue index ca88ce15b..cfdc4eca7 100644 --- a/src/components/tasks/gantt-component.vue +++ b/src/components/tasks/gantt-component.vue @@ -2,13 +2,6 @@
- - {{ $t('filters.title') }} - { - const store = useStorage(STORAGE_KEY, DEFAULT_COLOR_SCHEME_SETTING) + const store = useStorage(STORAGE_KEY, DEFAULT_COLOR_SCHEME_SETTING) const preferredColorScheme = usePreferredColorScheme() diff --git a/src/i18n/lang/cs-CZ.json b/src/i18n/lang/cs-CZ.json index 248ee2caf..8ebcc352d 100644 --- a/src/i18n/lang/cs-CZ.json +++ b/src/i18n/lang/cs-CZ.json @@ -901,7 +901,7 @@ "5010": "Tento tým nemá k tomuto prostoru přístup.", "5011": "Tento uživatel již má přístup k tomuto prostoru.", "5012": "Prostor je archivován, a proto je přístupný pouze pro čtení.", - "6001": "Název týmu nemůže být prázdný.", + "6001": "The team name cannot be empty.", "6002": "Tým neexistuje.", "6004": "Tým již má přístup k tomuto prostoru nebo seznamu.", "6005": "Uživatel je již členem tohoto týmu.", diff --git a/src/i18n/lang/de-DE.json b/src/i18n/lang/de-DE.json index 509d8acb7..f2d57a937 100644 --- a/src/i18n/lang/de-DE.json +++ b/src/i18n/lang/de-DE.json @@ -114,12 +114,12 @@ "vikunja": "Vikunja" }, "appearance": { - "title": "Color Scheme", - "setSuccess": "Saved change of color scheme to {colorScheme}", + "title": "Farbschema", + "setSuccess": "Änderung des Farbschemas auf {colorScheme} gespeichert", "colorScheme": { - "light": "Light", + "light": "Hell", "system": "System", - "dark": "Dark" + "dark": "Dunkel" } } }, @@ -556,7 +556,7 @@ "text2": "Dies wird auch alle Anhänge, Erinnerungen und Verknüpfungen, die zu dieser Aufgabe gehören löschen und kann nicht rückgängig gemacht werden!" }, "actions": { - "assign": "Assign to a user", + "assign": "Benutzer:in zuweisen", "label": "Label hinzufügen", "priority": "Priorität setzen", "dueDate": "Fälligkeitsdatum setzen", @@ -775,7 +775,7 @@ "task": { "title": "Aufgabenseite", "done": "Eine Aufgabe als erledigt markieren", - "assign": "Assign to a user", + "assign": "Benutzer:in zuweisen", "labels": "Dieser Aufgabe ein Label hinzufügen", "dueDate": "Ändere das Fälligkeitsdatum dieser Aufgabe", "attachment": "Einen Anhang dieser Aufgabe hinzufügen", diff --git a/src/i18n/lang/de-swiss.json b/src/i18n/lang/de-swiss.json index 21b697624..d35125e5b 100644 --- a/src/i18n/lang/de-swiss.json +++ b/src/i18n/lang/de-swiss.json @@ -114,12 +114,12 @@ "vikunja": "Vikunja" }, "appearance": { - "title": "Color Scheme", - "setSuccess": "Saved change of color scheme to {colorScheme}", + "title": "Farbschema", + "setSuccess": "Änderung des Farbschemas auf {colorScheme} gespeichert", "colorScheme": { - "light": "Light", + "light": "Hell", "system": "System", - "dark": "Dark" + "dark": "Dunkel" } } }, @@ -556,7 +556,7 @@ "text2": "Das wird au alli Ahhäng, Errinnerige und Beziehige wo mit dere Uufgab verchnüpft sind chüble und cha nid rückgängig gmacht werde!" }, "actions": { - "assign": "Assign to a user", + "assign": "Benutzer:in zuweisen", "label": "Label hinzuefüege", "priority": "Priorität setzä", "dueDate": "Fälligkeitsdatum setze", @@ -775,7 +775,7 @@ "task": { "title": "Uufgabesiite", "done": "Uufgab als erledigt markiere", - "assign": "Assign to a user", + "assign": "Benutzer:in zuweisen", "labels": "Labels ennere Uufgab hinzuefüege", "dueDate": "S'Fälligkeitsdatum für die Uufgab ändere", "attachment": "En Aahang dere Uufgab hinzuefüege", @@ -901,7 +901,7 @@ "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.", "6004": "Da Team het scho Zuegang zu dem Namensruum oder Liste.", "6005": "De Benutzer isch scho bi dem Team.", diff --git a/src/i18n/lang/en.json b/src/i18n/lang/en.json index a0366b2ce..4a939660c 100644 --- a/src/i18n/lang/en.json +++ b/src/i18n/lang/en.json @@ -901,7 +901,7 @@ "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 emtpy.", + "6001": "The team name cannot be empty.", "6002": "The team does not exist.", "6004": "The team already has access to that namespace or list.", "6005": "The user is already a member of that team.", diff --git a/src/i18n/lang/es-ES.json b/src/i18n/lang/es-ES.json index a0366b2ce..4a939660c 100644 --- a/src/i18n/lang/es-ES.json +++ b/src/i18n/lang/es-ES.json @@ -901,7 +901,7 @@ "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 emtpy.", + "6001": "The team name cannot be empty.", "6002": "The team does not exist.", "6004": "The team already has access to that namespace or list.", "6005": "The user is already a member of that team.", diff --git a/src/i18n/lang/fr-FR.json b/src/i18n/lang/fr-FR.json index 342bab076..88a30c07f 100644 --- a/src/i18n/lang/fr-FR.json +++ b/src/i18n/lang/fr-FR.json @@ -901,7 +901,7 @@ "5010": "Cette équipe n’a pas accès à cet espace de noms.", "5011": "Cet·e utilisateur·rice a déjà accès à cet espace de noms.", "5012": "L’espace de noms est archivé et ne peut donc être consulté qu’en lecture seule.", - "6001": "Le nom de l’équipe ne peut pas être vide.", + "6001": "The team name cannot be empty.", "6002": "L’équipe n’existe pas.", "6004": "L’équipe a déjà accès à cet espace de noms ou à cette liste.", "6005": "L’utilisateur·rice est déjà membre de cette équipe.", diff --git a/src/i18n/lang/it-IT.json b/src/i18n/lang/it-IT.json index 438a436d5..8190677d6 100644 --- a/src/i18n/lang/it-IT.json +++ b/src/i18n/lang/it-IT.json @@ -901,7 +901,7 @@ "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 emtpy.", + "6001": "The team name cannot be empty.", "6002": "The team does not exist.", "6004": "The team already has access to that namespace or list.", "6005": "The user is already a member of that team.", diff --git a/src/i18n/lang/nl-NL.json b/src/i18n/lang/nl-NL.json index a0366b2ce..4a939660c 100644 --- a/src/i18n/lang/nl-NL.json +++ b/src/i18n/lang/nl-NL.json @@ -901,7 +901,7 @@ "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 emtpy.", + "6001": "The team name cannot be empty.", "6002": "The team does not exist.", "6004": "The team already has access to that namespace or list.", "6005": "The user is already a member of that team.", diff --git a/src/i18n/lang/pt-BR.json b/src/i18n/lang/pt-BR.json index a0366b2ce..4a939660c 100644 --- a/src/i18n/lang/pt-BR.json +++ b/src/i18n/lang/pt-BR.json @@ -901,7 +901,7 @@ "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 emtpy.", + "6001": "The team name cannot be empty.", "6002": "The team does not exist.", "6004": "The team already has access to that namespace or list.", "6005": "The user is already a member of that team.", diff --git a/src/i18n/lang/pt-PT.json b/src/i18n/lang/pt-PT.json index a0366b2ce..4a939660c 100644 --- a/src/i18n/lang/pt-PT.json +++ b/src/i18n/lang/pt-PT.json @@ -901,7 +901,7 @@ "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 emtpy.", + "6001": "The team name cannot be empty.", "6002": "The team does not exist.", "6004": "The team already has access to that namespace or list.", "6005": "The user is already a member of that team.", diff --git a/src/i18n/lang/ro-RO.json b/src/i18n/lang/ro-RO.json index a0366b2ce..4a939660c 100644 --- a/src/i18n/lang/ro-RO.json +++ b/src/i18n/lang/ro-RO.json @@ -901,7 +901,7 @@ "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 emtpy.", + "6001": "The team name cannot be empty.", "6002": "The team does not exist.", "6004": "The team already has access to that namespace or list.", "6005": "The user is already a member of that team.", diff --git a/src/i18n/lang/ru-RU.json b/src/i18n/lang/ru-RU.json index fb92d727a..0abea93ad 100644 --- a/src/i18n/lang/ru-RU.json +++ b/src/i18n/lang/ru-RU.json @@ -901,7 +901,7 @@ "5010": "У этой команды нет доступа к этому пространству имён.", "5011": "Этот пользователь уже имеет доступ к этому пространству имён.", "5012": "Это пространство имён архивировано и поэтому доступно только для чтения.", - "6001": "Имя команды не может быть пустым.", + "6001": "The team name cannot be empty.", "6002": "Команда не существует.", "6004": "Эта команда уже имеет доступ к этому пространству имён или списку.", "6005": "Пользователь уже является участником этой команды.", diff --git a/src/i18n/lang/sv-SE.json b/src/i18n/lang/sv-SE.json new file mode 100644 index 000000000..4a939660c --- /dev/null +++ b/src/i18n/lang/sv-SE.json @@ -0,0 +1,933 @@ +{ + "home": { + "welcomeNight": "Good Night {username}", + "welcomeMorning": "Good Morning {username}", + "welcomeDay": "Hi {username}", + "welcomeEvening": "Good Evening {username}", + "lastViewed": "Last viewed", + "list": { + "newText": "You can create a new list for your new tasks:", + "new": "Create a new list", + "importText": "Or import your lists and tasks from other services into Vikunja:", + "import": "Import your data into Vikunja" + } + }, + "404": { + "title": "Not found", + "text": "The page you requested does not exist." + }, + "ready": { + "loading": "Vikunja is loading…", + "errorOccured": "An error occured:", + "checkApiUrl": "Please check if the api url is correct.", + "noApiUrlConfigured": "No API url was configured. Please set one below:" + }, + "offline": { + "title": "You are offline.", + "text": "Please check your network connection and try again." + }, + "user": { + "auth": { + "username": "Username", + "usernameEmail": "Username Or Email Address", + "usernamePlaceholder": "e.g. frederick", + "email": "E-mail address", + "emailPlaceholder": "e.g. frederic{'@'}vikunja.io", + "password": "Password", + "passwordRepeat": "Retype your password", + "passwordPlaceholder": "e.g. •••••••••••", + "resetPassword": "Reset your password", + "resetPasswordAction": "Send me a password reset link", + "resetPasswordSuccess": "Check your inbox! You should have an e-mail with instructions on how to reset your password.", + "passwordsDontMatch": "Passwords don't match", + "confirmEmailSuccess": "You successfully confirmed your email! You can log in now.", + "totpTitle": "Two Factor Authentication Code", + "totpPlaceholder": "e.g. 123456", + "login": "Login", + "register": "Register", + "loginWith": "Log in with {provider}", + "authenticating": "Authenticating…", + "openIdStateError": "State does not match, refusing to continue!", + "openIdGeneralError": "An error occured while authenticating against the third party.", + "logout": "Logout" + }, + "settings": { + "title": "Settings", + "newPasswordTitle": "Update Your Password", + "newPassword": "New Password", + "newPasswordConfirm": "New Password Confirmation", + "currentPassword": "Current Password", + "currentPasswordPlaceholder": "Your current password", + "passwordsDontMatch": "The new password and its confirmation don't match.", + "passwordUpdateSuccess": "The password was successfully updated.", + "updateEmailTitle": "Update Your E-Mail Address", + "updateEmailNew": "New Email Address", + "updateEmailSuccess": "Your email address was successfully updated. We've sent you a link to confirm it.", + "general": { + "title": "General Settings", + "name": "Name", + "newName": "The new Name", + "savedSuccess": "The settings were successfully updated.", + "emailReminders": "Send me reminders for tasks via Email", + "overdueReminders": "Send me reminders for overdue undone tasks via email each morning", + "discoverableByName": "Let other users find me when they search for my name", + "discoverableByEmail": "Let other users find me when they search for my full email", + "playSoundWhenDone": "Play a sound when marking tasks as done", + "weekStart": "Week starts on", + "weekStartSunday": "Sunday", + "weekStartMonday": "Monday", + "language": "Language", + "defaultList": "Default List" + }, + "totp": { + "title": "Two Factor Authentication", + "enroll": "Enroll", + "finishSetupPart1": "To finish your setup, use this secret in your totp app (Google Authenticator or similar):", + "finishSetupPart2": "After that, enter a code from your app below.", + "scanQR": "Alternatively you can scan this QR code:", + "passcode": "Passcode", + "passcodePlaceholder": "A code generated by your totp application", + "setupSuccess": "You've sucessfully set up two factor authentication!", + "enterPassword": "Please Enter Your Password", + "disable": "Disable two factor authentication", + "confirmSuccess": "You've successfully confirmed your totp setup and can use it from now on!", + "disableSuccess": "Two factor authentication was sucessfully disabled." + }, + "caldav": { + "title": "Caldav", + "howTo": "You can connect Vikunja to caldav clients to view and manage all tasks from different clients. Enter this url into your client:", + "more": "More information about caldav in Vikunja" + }, + "avatar": { + "title": "Avatar", + "initials": "Initials", + "gravatar": "Gravatar", + "upload": "Upload", + "uploadAvatar": "Upload Avatar", + "statusUpdateSuccess": "Avatar status was updated successfully!", + "setSuccess": "The avatar has been set successfully!" + }, + "quickAddMagic": { + "title": "Quick Add Magic Mode", + "disabled": "Disabled", + "todoist": "Todoist", + "vikunja": "Vikunja" + }, + "appearance": { + "title": "Color Scheme", + "setSuccess": "Saved change of color scheme to {colorScheme}", + "colorScheme": { + "light": "Light", + "system": "System", + "dark": "Dark" + } + } + }, + "deletion": { + "title": "Delete your Vikunja Account", + "text1": "The deletion of your account is permanent and cannot be undone. We will delete all your namespaces, lists, tasks and everything associated with it.", + "text2": "To proceed, please enter your password. You will receive an email with further instructions.", + "confirm": "Delete my account", + "requestSuccess": "The request was successful. You'll receive an email with further instructions.", + "passwordRequired": "Please enter your password.", + "confirmSuccess": "You've successfully confirmed the deletion of your account. We will delete your account in three days.", + "scheduled": "We will delete your Vikunja account at {date} ({dateSince}).", + "scheduledCancel": "To cancel the deletion of your account, click here.", + "scheduledCancelText": "To cancel the deletion of your account, please enter your password below:", + "scheduledCancelConfirm": "Cancel the deletion of my account", + "scheduledCancelSuccess": "We will not delete your account." + }, + "export": { + "title": "Export your Vikunja data", + "description": "You can request a copy of all your Vikunja data. This include Namespaces, Lists, 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:", + "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.", + "downloadTitle": "Download your exported Vikunja data" + } + }, + "list": { + "archived": "This list is archived. It is not possible to create new or edit tasks for it.", + "title": "List Title", + "color": "Color", + "lists": "Lists", + "search": "Type to search for a list…", + "searchSelect": "Click or press enter to select this list", + "shared": "Shared Lists", + "create": { + "header": "Create a new list", + "titlePlaceholder": "The list's title goes here…", + "addTitleRequired": "Please specify a title.", + "createdSuccess": "The list was successfully created.", + "addListRequired": "Please specify a list or set a default list in the settings." + }, + "archive": { + "title": "Archive \"{list}\"", + "archive": "Archive this list", + "unarchive": "Un-Archive this list", + "unarchiveText": "You will be able to create new tasks or edit it.", + "archiveText": "You won't be able to edit this list or create new tasks until you un-archive it.", + "success": "The list was successfully archived." + }, + "background": { + "title": "Set list background", + "remove": "Remove Background", + "upload": "Choose a background from your pc", + "searchPlaceholder": "Search for a background…", + "poweredByUnsplash": "Powered by Unsplash", + "loadMore": "Load more photos", + "success": "The background has been set successfully!", + "removeSuccess": "The background has been removed successfully!" + }, + "delete": { + "title": "Delete \"{list}\"", + "header": "Delete this list", + "text1": "Are you sure you want to delete this list and all of its contents?", + "text2": "This includes all tasks and CANNOT BE UNDONE!", + "success": "The list was successfully deleted." + }, + "duplicate": { + "title": "Duplicate this list", + "label": "Duplicate", + "text": "Select a namespace which should hold the duplicated list:", + "success": "The list was successfully duplicated." + }, + "edit": { + "header": "Edit This List", + "title": "Edit \"{list}\"", + "titlePlaceholder": "The list title goes here…", + "identifierTooltip": "The list identifier can be used to uniquely identify a task across lists. You can set it to empty to disable it.", + "identifier": "List Identifier", + "identifierPlaceholder": "The list identifier goes here…", + "description": "Description", + "descriptionPlaceholder": "The lists description goes here…", + "color": "Color", + "success": "The list was successfully updated." + }, + "share": { + "header": "Share this list", + "title": "Share \"{list}\"", + "share": "Share", + "links": { + "title": "Share Links", + "what": "What is a share link?", + "explanation": "Share Links allow you to easily share a list with other users who don't have an account on Vikunja.", + "create": "Create a new link share", + "name": "Name (optional)", + "namePlaceholder": "e.g. Lorem Ipsum", + "nameExplanation": "All actions done by this link share will show up with the name.", + "password": "Password (optional)", + "passwordExplanation": "When authenticating, the user will be required to enter this password.", + "noName": "No name set", + "remove": "Remove a link share", + "removeText": "Are you sure you want to remove this link share? It will no longer be possible to access this list with this link share. This cannot be undone!", + "createSuccess": "The link share was successfully created.", + "deleteSuccess": "The link share was successfully deleted" + }, + "userTeam": { + "typeUser": "user | users", + "typeTeam": "team | teams", + "shared": "Shared with these {type}", + "you": "You", + "notShared": "Not shared with any {type} yet.", + "removeHeader": "Remove a {type} from the {sharable}", + "removeText": "Are you sure you want to remove this {sharable} from the {type}? This cannot be undone!", + "removeSuccess": "The {sharable} was successfully removed from the {type}.", + "addedSuccess": "The {type} was successfully added.", + "updatedSuccess": "The {type} was successfully added." + }, + "right": { + "title": "Right", + "read": "Read only", + "readWrite": "Read & write", + "admin": "Admin" + }, + "attributes": { + "link": "Link", + "name": "Name", + "sharedBy": "Shared by", + "right": "Right", + "delete": "Delete" + } + }, + "list": { + "title": "List", + "add": "Add", + "addPlaceholder": "Add a new task…", + "empty": "This list is currently empty.", + "newTaskCta": "Create a new task.", + "editTask": "Edit Task" + }, + "gantt": { + "title": "Gantt", + "showTasksWithoutDates": "Show tasks which don't have dates set", + "size": "Size", + "default": "Default", + "month": "Month", + "day": "Day", + "from": "From", + "to": "To", + "noDates": "This task has no dates set." + }, + "table": { + "title": "Table", + "columns": "Columns" + }, + "kanban": { + "title": "Kanban", + "limit": "Limit: {limit}", + "noLimit": "Not Set", + "doneBucket": "Done bucket", + "doneBucketHint": "All tasks moved into this bucket will automatically marked as done.", + "doneBucketHintExtended": "All tasks moved into the done bucket will be marked as done automatically. All tasks marked as done from elsewhere will be moved as well.", + "doneBucketSavedSuccess": "The done bucket has been saved successfully.", + "deleteLast": "You cannot remove the last bucket.", + "addTaskPlaceholder": "Enter the new task title…", + "addTask": "Add a task", + "addAnotherTask": "Add another task", + "addBucket": "Create a new bucket", + "addBucketPlaceholder": "Enter the new bucket title…", + "deleteHeaderBucket": "Delete the bucket", + "deleteBucketText1": "Are you sure you want to delete this bucket?", + "deleteBucketText2": "This will not delete any tasks but move them into the default bucket.", + "deleteBucketSuccess": "The bucket has been deleted successfully.", + "bucketTitleSavedSuccess": "The bucket title has been saved successfully.", + "bucketLimitSavedSuccess": "The bucket limit been saved successfully.", + "collapse": "Collapse this bucket" + }, + "pseudo": { + "favorites": { + "title": "Favorites" + } + } + }, + "namespace": { + "title": "Namespaces & Lists", + "namespace": "Namespace", + "showArchived": "Show Archived", + "noneAvailable": "You don't have any namespaces right now.", + "unarchive": "Un-Archive", + "archived": "Archived", + "noLists": "This namespace does not contain any lists.", + "createList": "Create a new list in this namespace.", + "namespaces": "Namespaces", + "search": "Type to search for a namespace…", + "create": { + "title": "Create a new namespace", + "titleRequired": "Please specify a title.", + "explanation": "A namespace is a collection of lists you can share and use to organize your lists with. In fact, every list belongs to a namepace.", + "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 lists until you un-archive it. This will also archive all lists in this namespace.", + "unarchiveText": "You will be able to create new lists or edit it.", + "success": "The namespace was successfully archived.", + "description": "If a namespace is archived, you cannot create new lists 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 lists 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": { + "sharedLists": { + "title": "Shared Lists" + }, + "favorites": { + "title": "Favorites" + }, + "savedFilters": { + "title": "Filters" + } + } + }, + "filters": { + "title": "Filters", + "clear": "Clear Filters", + "attributes": { + "title": "Title", + "titlePlaceholder": "The saved filter title goes here…", + "description": "Description", + "descriptionPlaceholder": "The description goes here…", + "includeNulls": "Include Tasks which don't have a value set", + "requireAll": "Require all filters to be true for a task to show up", + "showDoneTasks": "Show Done Tasks", + "enablePriority": "Enable Filter By Priority", + "enablePercentDone": "Enable Filter By Percent Done", + "dueDateRange": "Due Date Range", + "startDateRange": "Start Date Range", + "endDateRange": "End Date Range", + "reminderRange": "Reminder Date Range" + }, + "create": { + "title": "Create A Saved Filter", + "description": "A saved filter is a virtual list which is computed from a set of filters each time it is accessed. Once created, it will appear in a special namespace.", + "action": "Create new saved filter" + }, + "delete": { + "header": "Delete this saved filter", + "text": "Are you sure you want to delete this saved filter?", + "success": "The filter was deleted successfully." + }, + "edit": { + "title": "Edit This Saved Filter", + "success": "The filter was saved successfully." + } + }, + "migrate": { + "title": "Migrate from other services to Vikunja", + "titleService": "Import your data from {name} into Vikunja", + "import": "Import your data into Vikunja", + "description": "Click on the logo of one of the third-party services below to get started.", + "descriptionDo": "Vikunja will import all lists, tasks, notes, reminders and files you have access to.", + "authorize": "To authorize Vikunja to access your {name} Account, click the button below.", + "getStarted": "Get Started", + "inProgress": "Importing in progress…", + "alreadyMigrated1": "It looks like you've already imported your stuff from {name} at {date}.", + "alreadyMigrated2": "Importing again is possible, but might create duplicates. Are you sure?", + "confirm": "I am sure, please start migrating now!", + "importUpload": "To import data from {name} into Vikunja, click the button below to select a file.", + "upload": "Upload file" + }, + "label": { + "title": "Labels", + "manage": "Manage labels", + "description": "Click on a label to edit it. You can edit all labels you created, you can use all labels which are associated with a task to whose list you have access.", + "newCTA": "You currently do not have any labels.", + "search": "Type to search for a label…", + "create": { + "header": "New label", + "title": "Create a new label", + "titleRequired": "Please specify a title.", + "success": "The label was successfully created." + }, + "edit": { + "header": "Edit Label", + "forbidden": "You are not allowed to edit this label because you dont own it.", + "success": "The label was successfully updated." + }, + "deleteSuccess": "The label was successfully deleted.", + "attributes": { + "title": "Title", + "titlePlaceholder": "The label title goes here…", + "description": "Description", + "descriptionPlaceholder": "Label description", + "color": "Color" + } + }, + "sharing": { + "authenticating": "Authenticating…", + "passwordRequired": "This shared list requires a password. Please enter it below:", + "error": "An error occured.", + "invalidPassword": "The password is invalid." + }, + "navigation": { + "overview": "Overview", + "upcoming": "Upcoming", + "settings": "Settings", + "imprint": "Imprint", + "privacy": "Privacy Policy" + }, + "misc": { + "loading": "Loading…", + "save": "Save", + "delete": "Delete", + "confirm": "Confirm", + "cancel": "Cancel", + "refresh": "Refresh", + "disable": "Disable", + "copy": "Copy to clipboard", + "search": "Search", + "searchPlaceholder": "Type to search…", + "previous": "Previous", + "next": "Next", + "poweredBy": "Powered by Vikunja", + "info": "Info", + "create": "Create", + "doit": "Do it!", + "saving": "Saving…", + "saved": "Saved!", + "default": "Default", + "close": "Close", + "download": "Download", + "showMenu": "Show the menu", + "hideMenu": "Hide the menu" + }, + "input": { + "resetColor": "Reset Color", + "datepicker": { + "today": "Today", + "tomorrow": "Tomorrow", + "nextMonday": "Next Monday", + "thisWeekend": "This Weekend", + "laterThisWeek": "Later This Week", + "nextWeek": "Next Week", + "chooseDate": "Choose a date" + }, + "editor": { + "edit": "Edit", + "done": "Done", + "heading1": "Heading 1", + "heading2": "Heading 2", + "heading3": "Heading 3", + "headingSmaller": "Heading Smaller", + "headingBigger": "Heading Bigger", + "bold": "Bold", + "italic": "Italic", + "strikethrough": "Strikethrough", + "code": "Code", + "quote": "Quote", + "unorderedList": "Unordered List", + "orderedList": "Ordered List", + "cleanBlock": "Clean Block", + "link": "Link", + "image": "Image", + "table": "Table", + "horizontalRule": "Horizontal Rule", + "sideBySide": "Side By Side", + "guide": "Guide" + }, + "multiselect": { + "createPlaceholder": "Create new", + "selectPlaceholder": "Click or press enter to select" + } + }, + "task": { + "task": "Task", + "new": "Create a new task", + "delete": "Delete this task", + "createSuccess": "The task was successfully created.", + "addReminder": "Add a new reminder…", + "doneSuccess": "The task was successfully marked as done.", + "undoneSuccess": "The task was successfully un-marked as done.", + "openDetail": "Open task detail view", + "checklistTotal": "{checked} of {total} tasks", + "checklistAllDone": "{total} tasks", + "show": { + "titleCurrent": "Current Tasks", + "titleDates": "Tasks from {from} until {to}", + "noDates": "Show tasks without dates", + "current": "Current tasks", + "from": "Tasks from", + "until": "until", + "today": "Today", + "nextWeek": "Next Week", + "nextMonth": "Next Month", + "noTasks": "Nothing to do — Have a nice day!" + }, + "detail": { + "chooseDueDate": "Click here to set a due date", + "chooseStartDate": "Click here to set a start date", + "chooseEndDate": "Click here to set an end date", + "move": "Move task to a different list", + "done": "Done!", + "undone": "Mark as undone", + "created": "Created {0} by {1}", + "updated": "Updated {0}", + "doneAt": "Done {0}", + "updateSuccess": "The task was saved successfully.", + "deleteSuccess": "The task has been deleted successfully.", + "belongsToList": "This task belongs to list '{list}'", + "due": "Due {at}", + "closePopup": "Close popup", + "delete": { + "header": "Delete this task", + "text1": "Are you sure you want to remove this task?", + "text2": "This will also remove all attachments, reminders and relations associated with this task and cannot be undone!" + }, + "actions": { + "assign": "Assign to a user", + "label": "Add labels", + "priority": "Set Priority", + "dueDate": "Set Due Date", + "startDate": "Set a Start Date", + "endDate": "Set an End Date", + "reminders": "Set Reminders", + "repeatAfter": "Set a repeating interval", + "percentDone": "Set Percent Done", + "attachments": "Add attachments", + "relatedTasks": "Add task relations", + "moveList": "Move task", + "color": "Set task color", + "delete": "Delete task", + "favorite": "Save as favorite", + "unfavorite": "Remove from favorites" + } + }, + "attributes": { + "assignees": "Assignees", + "color": "Color", + "created": "Created", + "createdBy": "Created By", + "description": "Description", + "done": "Done", + "dueDate": "Due Date", + "endDate": "End Date", + "labels": "Labels", + "percentDone": "% Done", + "priority": "Priority", + "relatedTasks": "Related Tasks", + "reminders": "Reminders", + "repeat": "Repeat", + "startDate": "Start Date", + "title": "Title", + "updated": "Updated" + }, + "subscription": { + "subscribedThroughParent": "You can't unsubscribe here because you are subscribed to this {entity} through its {parent}.", + "subscribed": "You are currently subscribed to this {entity} and will receive notifications for changes.", + "notSubscribed": "You are not subscribed to this {entity} and won't receive notifications for changes.", + "subscribe": "Subscribe", + "unsubscribe": "Unsubscribe", + "subscribeSuccess": "You are now subscribed to this {entity}", + "unsubscribeSuccess": "You are now unsubscribed to this {entity}" + }, + "attachment": { + "title": "Attachments", + "createdBy": "created {0} by {1}", + "downloadTooltip": "Download this attachment", + "upload": "Upload attachment", + "drop": "Drop files here to upload", + "delete": "Delete attachment", + "deleteTooltip": "Delete this attachment", + "deleteText1": "Are you sure you want to delete the attachment {filename}?", + "deleteText2": "This cannot be undone!", + "copyUrl": "Copy URL", + "copyUrlTooltip": "Copy the url of this attachment for usage in text" + }, + "comment": { + "title": "Comments", + "loading": "Loading comments…", + "edited": "edited {date}", + "creating": "Creating comment…", + "placeholder": "Add your comment…", + "comment": "Comment", + "delete": "Delete this comment", + "deleteText1": "Are you sure you want to delete this comment?", + "deleteText2": "This cannot be undone!", + "addedSuccess": "The comment was added successfully." + }, + "deferDueDate": { + "title": "Defer due date", + "1day": "1 day", + "3days": "3 days", + "1week": "1 week" + }, + "description": { + "placeholder": "Click here to enter a description…", + "empty": "No description available yet." + }, + "assignee": { + "placeholder": "Type to assign a user…", + "selectPlaceholder": "Assign this user", + "assignSuccess": "The user has been assigned successfully.", + "unassignSuccess": "The user has been unassigned successfully." + }, + "label": { + "placeholder": "Type to add a new label…", + "createPlaceholder": "Add this as new label", + "addSuccess": "The label has been added successfully.", + "createSuccess": "The label has been created successfully.", + "removeSuccess": "The label has been removed successfully.", + "addCreateSuccess": "The label has been created and added successfully." + }, + "priority": { + "unset": "Unset", + "low": "Low", + "medium": "Medium", + "high": "high", + "urgent": "Urgent", + "doNow": "DO NOW" + }, + "relation": { + "add": "Add a New Task Relation", + "new": "New Task Relation", + "searchPlaceholder": "Type search for a new task to add as related…", + "createPlaceholder": "Add this as new related task", + "differentList": "This task belongs to a different list.", + "differentNamespace": "This task belongs to a different namespace.", + "noneYet": "No task relations yet.", + "delete": "Delete Task Relation", + "deleteText1": "Are you sure you want to delete this task relation?", + "deleteText2": "This cannot be undone!", + "select": "Select a relation kind", + "kinds": { + "subtask": "Subtask | Subtasks", + "parenttask": "Parent Task | Parent Tasks", + "related": "Related Task | Related Tasks", + "duplicateof": "Duplicate Of | Duplicates Of", + "duplicates": "Duplicates | Duplicates", + "blocking": "Blocking | Blocking", + "blocked": "Blocked By | Blocked By", + "precedes": "Precedes | Precedes", + "follows": "Follows | Follows", + "copiedfrom": "Copied From | Copied From", + "copiedto": "Copied To | Copied To" + } + }, + "repeat": { + "everyDay": "Every Day", + "everyWeek": "Every Week", + "everyMonth": "Every Month", + "mode": "Repeat mode", + "monthly": "Monthly", + "fromCurrentDate": "From Current Date", + "each": "Each", + "specifyAmount": "Specify an amount…", + "hours": "Hours", + "days": "Days", + "weeks": "Weeks", + "months": "Months", + "years": "Years" + }, + "quickAddMagic": { + "hint": "You can use Quick Add Magic", + "what": "What?", + "title": "Quick Add Magic", + "intro": "When creating a task, you can use special keywords to directly add attributes to the newly created task. This allows to add commonly used attributes to tasks much faster.", + "multiple": "You can use this multiple times.", + "label1": "To add a label, simply prefix the name of the label with {prefix}.", + "label2": "Vikunja will first check if the label already exist and create it if not.", + "label3": "To use spaces, simply add a \" around the label name.", + "label4": "For example: {prefix}\"Label with spaces\".", + "priority1": "To set a task's priority, add a number 1-5, prefixed with a {prefix}.", + "priority2": "The higher the number, the higher the priority.", + "assignees": "To directly assign the task to a user, add their username prefixed with {prefix} to the task.", + "list1": "To set a list for the task to appear in, enter its name prefixed with {prefix}.", + "list2": "This will return an error if the list does not exist.", + "dateAndTime": "Date and time", + "date": "Any date will be used as the due date of the new task. You can use dates in any of these formats:", + "dateWeekday": "any weekday, will use the next date with that date", + "dateCurrentYear": "will use the current year", + "dateNth": "will use the {day}th of the current month", + "dateTime": "Combine any of the date formats with \"{time}\" (or {timePM}) to set a time." + } + }, + "team": { + "title": "Teams", + "noTeams": "You are currently not part of any teams.", + "create": { + "title": "Create a new team", + "success": "The team was successfully created." + }, + "edit": { + "title": "Edit Team \"{team}\"", + "members": "Team Members", + "search": "Type to search a user…", + "addUser": "Add to team", + "makeMember": "Make Member", + "makeAdmin": "Make Admin", + "success": "The team was successfully updated.", + "userAddedSuccess": "The team member was successfully added.", + "madeMember": "The team member was successfully made member.", + "madeAdmin": "The team member was successfully made admin.", + "delete": { + "header": "Delete the team", + "text1": "Are you sure you want to delete this team and all of its members?", + "text2": "All team members will lose access to lists and namespaces shared with this team. This CANNOT BE UNDONE!", + "success": "The team was successfully deleted." + }, + "deleteUser": { + "header": "Remove a user from the team", + "text1": "Are you sure you want to remove this user from the team?", + "text2": "They will lose access to all lists and namespaces this team has access to. This CANNOT BE UNDONE!", + "success": "The user was successfully deleted from the team." + } + }, + "attributes": { + "name": "Team Name", + "namePlaceholder": "The team's name goes here…", + "nameRequired": "Please specify a name.", + "description": "Description", + "descriptionPlaceholder": "The teams description goes here…", + "admin": "Admin", + "member": "Member" + } + }, + "keyboardShortcuts": { + "title": "Keyboard Shortcuts", + "general": "General", + "allPages": "These shortcuts work on all pages.", + "currentPageOnly": "These shortcuts work only on the current page.", + "toggleMenu": "Toggle The Menu", + "quickSearch": "Open the search/quick action bar", + "then": "then", + "task": { + "title": "Task Page", + "done": "Mark a task as done", + "assign": "Assign to a user", + "labels": "Add labels to this task", + "dueDate": "Change the due date of this task", + "attachment": "Add an attachment to this task", + "related": "Modify related tasks of this task" + }, + "list": { + "title": "List Views", + "switchToListView": "Switch to list view", + "switchToGanttView": "Switch to gantt view", + "switchToKanbanView": "Switch to kanban view", + "switchToTableView": "Switch to table view" + } + }, + "update": { + "available": "There is an update for Vikunja available!", + "do": "Update Now" + }, + "menu": { + "edit": "Edit", + "archive": "Archive", + "duplicate": "Duplicate", + "delete": "Delete", + "unarchive": "Un-Archive", + "setBackground": "Set background", + "share": "Share", + "newList": "New list" + }, + "apiConfig": { + "url": "Vikunja URL", + "urlPlaceholder": "eg. https://localhost:3456", + "change": "change", + "signInOn": "Sign in to your Vikunja account on {0}", + "error": "Could not find or use Vikunja installation at \"{domain}\". Please try a different url.", + "success": "Using Vikunja installation at \"{domain}\".", + "urlRequired": "A url is required." + }, + "loadingError": { + "failed": "Loading failed, please {0}. If the error persists, please {1}.", + "tryAgain": "try again", + "contact": "contact us" + }, + "notification": { + "title": "Notifications", + "none": "You don't have any notifications. Have a nice day!", + "explainer": "Notifications will appear here when actions on namespaces, lists or tasks you subscribed to happen." + }, + "quickActions": { + "commands": "Commands", + "placeholder": "Type a command or search…", + "hint": "You can use {list} to limit the search to a list. Combine {list} or {label} (labels) with a search query to search for a task with these labels or on that list. Use {assignee} to only search for teams.", + "tasks": "Tasks", + "lists": "Lists", + "teams": "Teams", + "newList": "Enter the title of the new list…", + "newTask": "Enter the title of the new task…", + "newNamespace": "Enter the title of the new namespace…", + "newTeam": "Enter the name of the new team…", + "createTask": "Create a task in the current list ({title})", + "createList": "Create a list in the current namespace ({title})", + "cmds": { + "newTask": "New task", + "newList": "New list", + "newNamespace": "New namespace", + "newTeam": "New team" + } + }, + "date": { + "locale": "en", + "altFormatLong": "j M Y H:i", + "altFormatShort": "j M Y" + }, + "error": { + "error": "Error", + "success": "Success", + "0001": "You're not allowed to do that.", + "1001": "A user with this username already exists.", + "1002": "A user with this email address already exists.", + "1004": "No username and password specified.", + "1005": "The user does not exist.", + "1006": "Could not get the user id.", + "1008": "No password reset token provided.", + "1009": "Invalid password reset token.", + "1010": "Invalid email confirm token.", + "1011": "Wrong username or password.", + "1012": "Email address of the user not confirmed.", + "1013": "New password is empty.", + "1014": "Old password is empty.", + "1015": "Totp is already enabled for this user.", + "1016": "Totp is not enabled for this user.", + "1017": "The totp passcode is invalid.", + "1018": "The user avatar type setting is invalid.", + "2001": "ID cannot be empty or 0.", + "2002": "Some of the request data was invalid.", + "3001": "The list does not exist.", + "3004": "You need to have read permissions on that list to perform that action.", + "3005": "The list title cannot be empty.", + "3006": "The list share does not exist.", + "3007": "A list with this identifier already exists.", + "3008": "The list is archived and can therefore only be accessed read only. This is also true for all tasks associated with this list.", + "4001": "The list task text cannot be empty.", + "4002": "The list task does not exist.", + "4003": "All bulk editing tasks must belong to the same list.", + "4004": "Need at least one task when bulk editing tasks.", + "4005": "You do not have the right to see the task.", + "4006": "You can't set a parent task as the task itself.", + "4007": "You can't create a task relation with an invalid kind of relation.", + "4008": "You can't create a task relation which already exists.", + "4009": "The task relation does not exist.", + "4010": "Cannot relate a task with itself.", + "4011": "The task attachment does not exist.", + "4012": "The task attachment is too large.", + "4013": "The task sort param is invalid.", + "4014": "The task sort order is invalid.", + "4015": "The task comment does not exist.", + "4016": "Invalid task field.", + "4017": "Invalid task filter comparator.", + "4018": "Invalid task filter concatinator.", + "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.", + "6002": "The team does not exist.", + "6004": "The team already has access to that namespace or list.", + "6005": "The user is already a member of that team.", + "6006": "Cannot delete the last team member.", + "6007": "The team does not have access to the list to perform that action.", + "7002": "The user already has access to that list.", + "7003": "You do not have access to that list.", + "8001": "This label already exists on that task.", + "8002": "The label does not exist.", + "8003": "You do not have access to this label.", + "9001": "The right is invalid.", + "10001": "The bucket does not exist.", + "10002": "The bucket does not belong to that list.", + "10003": "You cannot remove the last bucket on a list.", + "10004": "You cannot add the task to this bucket as it already exceeded the limit of tasks it can hold.", + "10005": "There can be only one done bucket per list.", + "11001": "The saved filter does not exist.", + "11002": "Saved filters are not available for link shares.", + "12001": "The subscription entity type is invalid.", + "12002": "You are already subscribed to the entity itself or a parent entity.", + "13001": "This link share requires a password for authentication, but none was provided.", + "13002": "The provided link share password was invalid." + }, + "about": { + "title": "About", + "frontendVersion": "Frontend Version: {version}", + "apiVersion": "API Version: {version}" + } +} diff --git a/src/i18n/lang/tr-TR.json b/src/i18n/lang/tr-TR.json index a0366b2ce..4a939660c 100644 --- a/src/i18n/lang/tr-TR.json +++ b/src/i18n/lang/tr-TR.json @@ -901,7 +901,7 @@ "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 emtpy.", + "6001": "The team name cannot be empty.", "6002": "The team does not exist.", "6004": "The team already has access to that namespace or list.", "6005": "The user is already a member of that team.", diff --git a/src/i18n/lang/vi-VN.json b/src/i18n/lang/vi-VN.json index 7bba63001..67ff213e2 100644 --- a/src/i18n/lang/vi-VN.json +++ b/src/i18n/lang/vi-VN.json @@ -114,12 +114,12 @@ "vikunja": "Vikunja" }, "appearance": { - "title": "Color Scheme", - "setSuccess": "Saved change of color scheme to {colorScheme}", + "title": "Phối màu", + "setSuccess": "Đã lưu phối màu vào {colorScheme}", "colorScheme": { - "light": "Light", - "system": "System", - "dark": "Dark" + "light": "Sáng", + "system": "Hệ thống", + "dark": "Tối" } } }, @@ -556,7 +556,7 @@ "text2": "Thao tác này cũng sẽ xóa tất cả tệp đính kèm, lời nhắc và liên kết đến công việc này. Nó không thể hoàn tác!" }, "actions": { - "assign": "Assign to a user", + "assign": "Chỉ định một người", "label": "Thêm nhãn", "priority": "Mức độ ưu tiên", "dueDate": "Đặt ngày đến hạn", @@ -775,7 +775,7 @@ "task": { "title": "Trang công việc", "done": "Đánh dấu hoàn thành", - "assign": "Assign to a user", + "assign": "Chỉ định một người", "labels": "Thêm nhãn cho công việc này", "dueDate": "Thay đổi ngày hết hạn của công việc này", "attachment": "Thêm tệp đính kèm cho công việc này", @@ -901,7 +901,7 @@ "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": "Team cũng cần có tên gọi mà.", + "6001": "The team name cannot be empty.", "6002": "Team không tồn tại.", "6004": "Team đã có quyền bước vào góc làm việc và xem danh sách.", "6005": "Người này đã là thành viên của Team đó rồi.", diff --git a/src/styles/common-imports.scss b/src/styles/common-imports.scss index bfcbfe6b6..b4e6032ed 100644 --- a/src/styles/common-imports.scss +++ b/src/styles/common-imports.scss @@ -19,14 +19,12 @@ $mobile: math.div($tablet, 2); $family-sans-serif: 'Open Sans', Helvetica, Arial, sans-serif; $vikunja-font: 'Quicksand', sans-serif; -$thickness: 1px; $pagination-current-border: var(--primary); $navbar-item-active-color: var(--primary); $dropdown-content-shadow: none; $dropdown-item-hover-background-color: var(--grey-100); -$bulmaswatch-import-font: false !default; $site-background: var(--grey-100); $transition-duration: 150ms; diff --git a/src/styles/custom-properties/colors.scss b/src/styles/custom-properties/colors.scss index 3b23f3eed..2fc3ba0d0 100644 --- a/src/styles/custom-properties/colors.scss +++ b/src/styles/custom-properties/colors.scss @@ -79,6 +79,8 @@ --link: var(--primary); --link-hover: hsla(var(--primary-h), var(--primary-s), var(--primary-l), .75); --border: var(--grey-200); + --input-disabled-background-color: var(--grey-100); + --input-disabled-border-color: var(--grey-300); &.dark { // Light mode colours reversed for dark mode diff --git a/src/styles/global.scss b/src/styles/global.scss index f4bea3171..6e357958b 100644 --- a/src/styles/global.scss +++ b/src/styles/global.scss @@ -23,7 +23,7 @@ @import "@bulvar/bulma/sass/elements/content"; @import "@bulvar/bulma/sass/elements/icon"; @import "@bulvar/bulma/sass/elements/image"; -@import "@bulvar/bulma/sass/elements/notification"; +// @import "@bulvar/bulma/sass/elements/notification"; // not used @import "@bulvar/bulma/sass/elements/progress"; @import "@bulvar/bulma/sass/elements/table"; @import "@bulvar/bulma/sass/elements/tag"; @@ -48,7 +48,7 @@ // @import "@bulvar/bulma/sass/components/level"; // not used @import "@bulvar/bulma/sass/components/media"; @import "@bulvar/bulma/sass/components/menu"; -@import "@bulvar/bulma/sass/components/message"; +// @import "@bulvar/bulma/sass/components/message"; //not used @import "@bulvar/bulma/sass/components/modal"; @import "@bulvar/bulma/sass/components/navbar"; @import "@bulvar/bulma/sass/components/pagination"; diff --git a/src/styles/theme/_index.scss b/src/styles/theme/_index.scss index 2c1a5b44b..b3eb47e0a 100644 --- a/src/styles/theme/_index.scss +++ b/src/styles/theme/_index.scss @@ -7,4 +7,4 @@ @import "form"; @import "link-share"; @import "loading"; -@import "notification"; \ No newline at end of file +@import "flatpickr"; \ No newline at end of file diff --git a/src/styles/theme/flatpickr.scss b/src/styles/theme/flatpickr.scss new file mode 100644 index 000000000..1a21ca1f9 --- /dev/null +++ b/src/styles/theme/flatpickr.scss @@ -0,0 +1,221 @@ +// Flatpickr overrides to use css custom properties and enable styling it + +.flatpickr-calendar { + background: var(--white); + box-shadow: 1px 0 0 var(--grey-200), -1px 0 0 var(--grey-200), 0 1px 0 var(--grey-200), 0 -1px 0 var(--grey-200), 0 3px 13px rgba(0, 0, 0, 0.08); +} + +.flatpickr-calendar.multiMonth .flatpickr-days .dayContainer:nth-child(n+2) .flatpickr-day.inRange:nth-child(7n+1) { + box-shadow: -2px 0 0 var(--grey-200), 5px 0 0 var(--grey-200); +} + +.flatpickr-calendar.hasTime .flatpickr-time { + border-top: 1px solid var(--grey-200); +} + +.flatpickr-calendar.arrowTop:before { + border-bottom-color: var(--grey-200); +} + +.flatpickr-calendar.arrowTop:after { + border-bottom-color: var(--white); +} + +.flatpickr-calendar.arrowBottom:before { + border-top-color: var(--grey-200); +} + +.flatpickr-calendar.arrowBottom:after { + border-top-color: var(--white); +} + +.flatpickr-months .flatpickr-month, +.flatpickr-months .flatpickr-prev-month, +.flatpickr-months .flatpickr-next-month { + color: var(--text); + fill: var(--grey-900); +} + +.flatpickr-months .flatpickr-prev-month:hover, +.flatpickr-months .flatpickr-next-month:hover { + color: var(--grey-400); +} + +.flatpickr-months .flatpickr-prev-month:hover svg, +.flatpickr-months .flatpickr-next-month:hover svg { + fill: var(--primary); +} + +.numInputWrapper span { + border: 1px solid var(--grey-200); +} + +.numInputWrapper span:hover { + background: var(--grey-800); +} + +.numInputWrapper span:active { + background: var(--grey-800); +} + +.numInputWrapper span.arrowUp:after { + border-bottom: 4px solid var(--grey-200); +} + +.numInputWrapper span.arrowDown:after { + border-top: 4px solid var(--grey-200); + top: 40%; +} + +.numInputWrapper span svg path { + fill: var(--grey-800); +} + +.numInputWrapper:hover { + background: var(--grey-100); +} + +.flatpickr-current-month span.cur-month:hover { + background: var(--grey-100); +} + +.flatpickr-current-month .numInputWrapper span.arrowUp:after { + border-bottom-color: var(--grey-900); +} + +.flatpickr-current-month .numInputWrapper span.arrowDown:after { + border-top-color: var(--grey-900); +} + +.flatpickr-current-month input.cur-year[disabled], +.flatpickr-current-month input.cur-year[disabled]:hover { + color: var(--grey-800); +} + +.flatpickr-current-month .flatpickr-monthDropdown-months:hover { + background: var(--grey-100); +} + +span.flatpickr-weekday { + color: var(--grey-600); +} + +.dayContainer + .dayContainer { + box-shadow: -1px 0 0 var(--grey-200); +} + +.flatpickr-day { + color: var(--grey-500); +} + +.flatpickr-day.inRange, +.flatpickr-day.prevMonthDay.inRange, +.flatpickr-day.nextMonthDay.inRange, +.flatpickr-day.today.inRange, +.flatpickr-day.prevMonthDay.today.inRange, +.flatpickr-day.nextMonthDay.today.inRange, +.flatpickr-day:hover, +.flatpickr-day.prevMonthDay:hover, +.flatpickr-day.nextMonthDay:hover, +.flatpickr-day:focus, +.flatpickr-day.prevMonthDay:focus, +.flatpickr-day.nextMonthDay:focus { + background: var(--grey-200); + border-color: var(--grey-200); +} + +.flatpickr-day.today { + border-color: var(--grey-400); +} + +.flatpickr-day.today:hover, +.flatpickr-day.today:focus { + border-color: var(--grey-400); + background: var(--grey-400); + color: var(--white); +} + +.flatpickr-day.selected, +.flatpickr-day.startRange, +.flatpickr-day.endRange, +.flatpickr-day.selected.inRange, +.flatpickr-day.startRange.inRange, +.flatpickr-day.endRange.inRange, +.flatpickr-day.selected:focus, +.flatpickr-day.startRange:focus, +.flatpickr-day.endRange:focus, +.flatpickr-day.selected:hover, +.flatpickr-day.startRange:hover, +.flatpickr-day.endRange:hover, +.flatpickr-day.selected.prevMonthDay, +.flatpickr-day.startRange.prevMonthDay, +.flatpickr-day.endRange.prevMonthDay, +.flatpickr-day.selected.nextMonthDay, +.flatpickr-day.startRange.nextMonthDay, +.flatpickr-day.endRange.nextMonthDay { + background: var(--primary); + color: var(--white); + border-color: var(--primary); +} + +.flatpickr-day.selected.startRange + .endRange:not(:nth-child(7n+1)), +.flatpickr-day.startRange.startRange + .endRange:not(:nth-child(7n+1)), +.flatpickr-day.endRange.startRange + .endRange:not(:nth-child(7n+1)) { + box-shadow: -10px 0 0 var(--primary); +} + +.flatpickr-day.inRange { + box-shadow: -5px 0 0 var(--grey-200), 5px 0 0 var(--grey-200); +} + +.flatpickr-day.flatpickr-disabled, +.flatpickr-day.flatpickr-disabled:hover, +.flatpickr-day.prevMonthDay, +.flatpickr-day.nextMonthDay, +.flatpickr-day.notAllowed, +.flatpickr-day.notAllowed.prevMonthDay, +.flatpickr-day.notAllowed.nextMonthDay { + color: var(--grey-300); +} + +.flatpickr-day.flatpickr-disabled, +.flatpickr-day.flatpickr-disabled:hover { + color: var(--grey-800); +} + +.flatpickr-day.week.selected { + box-shadow: -5px 0 0 var(--primary), 5px 0 0 var(--primary); +} + +.flatpickr-weekwrapper .flatpickr-weeks { + box-shadow: 1px 0 0 var(--grey-200); +} + +.flatpickr-weekwrapper span.flatpickr-day, +.flatpickr-weekwrapper span.flatpickr-day:hover { + color: var(--grey-300); +} + +.flatpickr-time .numInputWrapper span.arrowUp:after { + border-bottom-color: var(--grey-500); +} + +.flatpickr-time .numInputWrapper span.arrowDown:after { + border-top-color: var(--grey-500); +} + +.flatpickr-time input { + color: var(--grey-500); +} + +.flatpickr-time .flatpickr-time-separator, +.flatpickr-time .flatpickr-am-pm { + color: var(--grey-500); +} + +.flatpickr-time input:hover, +.flatpickr-time .flatpickr-am-pm:hover, +.flatpickr-time input:focus, +.flatpickr-time .flatpickr-am-pm:focus { + background: var(--grey-100); +} diff --git a/src/styles/theme/form.scss b/src/styles/theme/form.scss index b5bbf0c5c..86c78f2fd 100644 --- a/src/styles/theme/form.scss +++ b/src/styles/theme/form.scss @@ -40,6 +40,7 @@ } .select select { + $thickness: 1px; border-width: $thickness; &:not([multiple]) { diff --git a/src/styles/theme/notification.scss b/src/styles/theme/notification.scss deleted file mode 100644 index 9950b9606..000000000 --- a/src/styles/theme/notification.scss +++ /dev/null @@ -1,12 +0,0 @@ -.notification { - border: $thickness solid $border; -} - -.notifications { - left: 0.5rem !important; - bottom: 1rem !important; -} - -.message .message-body { - border: $thickness solid; -} diff --git a/src/views/Home.vue b/src/views/Home.vue index ea16c717a..b0c6c25d1 100644 --- a/src/views/Home.vue +++ b/src/views/Home.vue @@ -3,7 +3,7 @@

{{ $t(`home.welcome${welcome}`, {username: userInfo.name !== '' ? userInfo.name : userInfo.username}) }}!

-
+ {{ $t('user.deletion.scheduled', { date: formatDateShort(deletionScheduledAt), @@ -13,7 +13,7 @@ {{ $t('user.deletion.scheduledCancel') }} -
+ - @@ -147,7 +127,7 @@ export default { flex-wrap: wrap; max-height: calc(#{$list-height * 2} + #{$list-spacing * 2} - 4px); overflow: hidden; - + @media screen and (max-width: $mobile) { max-height: calc(#{$list-height * 4} + #{$list-spacing * 4} - 4px); } diff --git a/src/views/list/ShowList.vue b/src/views/list/ShowList.vue index 5ed589096..d0c1d20fe 100644 --- a/src/views/list/ShowList.vue +++ b/src/views/list/ShowList.vue @@ -36,9 +36,9 @@
-
+ {{ $t('list.archived') }} -
+
@@ -46,6 +46,7 @@