forked from vikunja/frontend
Compare commits
28 Commits
renovate/d
...
main
Author | SHA1 | Date | |
---|---|---|---|
3d35cbe984 | |||
298ef83b2e | |||
308ad23674 | |||
f6f915db86 | |||
b65abff122 | |||
336ce217d3 | |||
|
ce01085951 | ||
96a6d43a3f | |||
13d63e34aa | |||
a8441c72b8 | |||
230fa6ce66 | |||
069c491fbd | |||
a9eae95d67 | |||
50502d9d11 | |||
18af6edc82 | |||
d048b61eb3 | |||
996607e670 | |||
e33ebe1831 | |||
557b0ffec7 | |||
dae6cdb9d7 | |||
158e4d690f | |||
691eb84a99 | |||
698ee7e163 | |||
ce822573df | |||
198abee01d | |||
|
e5bea087be | ||
|
4956fbb669 | ||
0351148288 |
20
.drone.yml
20
.drone.yml
|
@ -42,7 +42,7 @@ steps:
|
|||
# - .cache
|
||||
|
||||
- name: dependencies
|
||||
image: node:20.10-alpine
|
||||
image: node:20.11-alpine
|
||||
pull: always
|
||||
environment:
|
||||
PNPM_CACHE_FOLDER: .cache/pnpm
|
||||
|
@ -55,7 +55,7 @@ steps:
|
|||
# - restore-cache
|
||||
|
||||
- name: lint
|
||||
image: node:20.10-alpine
|
||||
image: node:20.11-alpine
|
||||
pull: always
|
||||
environment:
|
||||
PNPM_CACHE_FOLDER: .cache/pnpm
|
||||
|
@ -66,7 +66,7 @@ steps:
|
|||
- dependencies
|
||||
|
||||
- name: build-prod
|
||||
image: node:20.10-alpine
|
||||
image: node:20.11-alpine
|
||||
pull: always
|
||||
environment:
|
||||
PNPM_CACHE_FOLDER: .cache/pnpm
|
||||
|
@ -77,7 +77,7 @@ steps:
|
|||
- dependencies
|
||||
|
||||
- name: test-unit
|
||||
image: node:20.10-alpine
|
||||
image: node:20.11-alpine
|
||||
pull: always
|
||||
commands:
|
||||
- corepack enable && pnpm config set store-dir .cache/pnpm
|
||||
|
@ -87,7 +87,7 @@ steps:
|
|||
|
||||
- name: typecheck
|
||||
failure: ignore
|
||||
image: node:20.10-alpine
|
||||
image: node:20.11-alpine
|
||||
pull: always
|
||||
environment:
|
||||
PNPM_CACHE_FOLDER: .cache/pnpm
|
||||
|
@ -202,7 +202,7 @@ steps:
|
|||
# - .cache
|
||||
|
||||
- name: build
|
||||
image: node:20.10-alpine
|
||||
image: node:20.11-alpine
|
||||
pull: always
|
||||
environment:
|
||||
PNPM_CACHE_FOLDER: .cache/pnpm
|
||||
|
@ -285,7 +285,7 @@ steps:
|
|||
# - .cache
|
||||
|
||||
- name: build
|
||||
image: node:20.10-alpine
|
||||
image: node:20.11-alpine
|
||||
pull: always
|
||||
environment:
|
||||
PNPM_CACHE_FOLDER: .cache/pnpm
|
||||
|
@ -486,7 +486,7 @@ trigger:
|
|||
steps:
|
||||
- name: download
|
||||
pull: always
|
||||
image: ghcr.io/lcomrade/lcomrade/drone-crowdin-v2:latest
|
||||
image: ghcr.io/kolaente/kolaente/drone-crowdin-v2:latest
|
||||
settings:
|
||||
crowdin_key:
|
||||
from_secret: crowdin_key
|
||||
|
@ -520,7 +520,7 @@ steps:
|
|||
|
||||
- name: upload
|
||||
pull: always
|
||||
image: ghcr.io/lcomrade/lcomrade/drone-crowdin-v2:latest
|
||||
image: ghcr.io/kolaente/kolaente/drone-crowdin-v2:latest
|
||||
depends_on:
|
||||
- clone
|
||||
settings:
|
||||
|
@ -532,6 +532,6 @@ steps:
|
|||
src/i18n/lang/en.json: en.json
|
||||
---
|
||||
kind: signature
|
||||
hmac: 1b78e92ee8a9aa94df14c35ea544abc0bec991ec59465c328a6aaa6cea4430b3
|
||||
hmac: c755a046a47f0b8a799a81a0c686cc4e7734938298c22b47a24e268aec3cf908
|
||||
|
||||
...
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# │─││ │││ │ │
|
||||
# ┘─┘┘─┘┘┘─┘┘─┘
|
||||
|
||||
FROM --platform=$BUILDPLATFORM node:20.10-alpine AS builder
|
||||
FROM --platform=$BUILDPLATFORM node:20.11-alpine AS builder
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
|
|
120
package.json
120
package.json
|
@ -13,7 +13,7 @@
|
|||
},
|
||||
"homepage": "https://vikunja.io/",
|
||||
"funding": "https://opencollective.com/vikunja",
|
||||
"packageManager": "pnpm@8.12.1",
|
||||
"packageManager": "pnpm@8.14.1",
|
||||
"keywords": [
|
||||
"todo",
|
||||
"productivity",
|
||||
|
@ -52,57 +52,57 @@
|
|||
"@github/hotkey": "3.1.0",
|
||||
"@infectoone/vue-ganttastic": "2.2.0",
|
||||
"@intlify/unplugin-vue-i18n": "2.0.0",
|
||||
"@kyvg/vue3-notification": "3.1.2",
|
||||
"@sentry/tracing": "7.88.0",
|
||||
"@sentry/vue": "7.88.0",
|
||||
"@tiptap/core": "2.1.13",
|
||||
"@tiptap/extension-blockquote": "2.1.13",
|
||||
"@tiptap/extension-bold": "2.1.13",
|
||||
"@tiptap/extension-bullet-list": "2.1.13",
|
||||
"@tiptap/extension-code": "2.1.13",
|
||||
"@tiptap/extension-code-block-lowlight": "2.1.13",
|
||||
"@tiptap/extension-document": "2.1.13",
|
||||
"@tiptap/extension-dropcursor": "2.1.13",
|
||||
"@tiptap/extension-gapcursor": "2.1.13",
|
||||
"@tiptap/extension-hard-break": "2.1.13",
|
||||
"@tiptap/extension-heading": "2.1.13",
|
||||
"@tiptap/extension-history": "2.1.13",
|
||||
"@tiptap/extension-horizontal-rule": "2.1.13",
|
||||
"@tiptap/extension-image": "2.1.13",
|
||||
"@tiptap/extension-italic": "2.1.13",
|
||||
"@tiptap/extension-link": "2.1.13",
|
||||
"@tiptap/extension-list-item": "2.1.13",
|
||||
"@tiptap/extension-ordered-list": "2.1.13",
|
||||
"@tiptap/extension-paragraph": "2.1.13",
|
||||
"@tiptap/extension-placeholder": "2.1.13",
|
||||
"@tiptap/extension-strike": "2.1.13",
|
||||
"@tiptap/extension-table": "2.1.13",
|
||||
"@tiptap/extension-table-cell": "2.1.13",
|
||||
"@tiptap/extension-table-header": "2.1.13",
|
||||
"@tiptap/extension-table-row": "2.1.13",
|
||||
"@tiptap/extension-task-item": "2.1.13",
|
||||
"@tiptap/extension-task-list": "2.1.13",
|
||||
"@tiptap/extension-text": "2.1.13",
|
||||
"@tiptap/extension-typography": "2.1.13",
|
||||
"@tiptap/extension-underline": "2.1.13",
|
||||
"@tiptap/pm": "2.1.13",
|
||||
"@tiptap/suggestion": "2.1.13",
|
||||
"@tiptap/vue-3": "2.1.13",
|
||||
"@kyvg/vue3-notification": "3.1.3",
|
||||
"@sentry/tracing": "7.93.0",
|
||||
"@sentry/vue": "7.93.0",
|
||||
"@tiptap/core": "2.1.15",
|
||||
"@tiptap/extension-blockquote": "2.1.15",
|
||||
"@tiptap/extension-bold": "2.1.15",
|
||||
"@tiptap/extension-bullet-list": "2.1.15",
|
||||
"@tiptap/extension-code": "2.1.15",
|
||||
"@tiptap/extension-code-block-lowlight": "2.1.15",
|
||||
"@tiptap/extension-document": "2.1.15",
|
||||
"@tiptap/extension-dropcursor": "2.1.15",
|
||||
"@tiptap/extension-gapcursor": "2.1.15",
|
||||
"@tiptap/extension-hard-break": "2.1.15",
|
||||
"@tiptap/extension-heading": "2.1.15",
|
||||
"@tiptap/extension-history": "2.1.15",
|
||||
"@tiptap/extension-horizontal-rule": "2.1.15",
|
||||
"@tiptap/extension-image": "2.1.15",
|
||||
"@tiptap/extension-italic": "2.1.15",
|
||||
"@tiptap/extension-link": "2.1.15",
|
||||
"@tiptap/extension-list-item": "2.1.15",
|
||||
"@tiptap/extension-ordered-list": "2.1.15",
|
||||
"@tiptap/extension-paragraph": "2.1.15",
|
||||
"@tiptap/extension-placeholder": "2.1.15",
|
||||
"@tiptap/extension-strike": "2.1.15",
|
||||
"@tiptap/extension-table": "2.1.15",
|
||||
"@tiptap/extension-table-cell": "2.1.15",
|
||||
"@tiptap/extension-table-header": "2.1.15",
|
||||
"@tiptap/extension-table-row": "2.1.15",
|
||||
"@tiptap/extension-task-item": "2.1.15",
|
||||
"@tiptap/extension-task-list": "2.1.15",
|
||||
"@tiptap/extension-text": "2.1.15",
|
||||
"@tiptap/extension-typography": "2.1.15",
|
||||
"@tiptap/extension-underline": "2.1.15",
|
||||
"@tiptap/pm": "2.1.15",
|
||||
"@tiptap/suggestion": "2.1.15",
|
||||
"@tiptap/vue-3": "2.1.15",
|
||||
"@types/is-touch-device": "1.0.2",
|
||||
"@types/lodash.clonedeep": "4.5.9",
|
||||
"@vueuse/core": "10.7.0",
|
||||
"@vueuse/router": "10.7.0",
|
||||
"axios": "1.6.2",
|
||||
"@vueuse/core": "10.7.1",
|
||||
"@vueuse/router": "10.7.1",
|
||||
"axios": "1.6.5",
|
||||
"blurhash": "2.0.5",
|
||||
"bulma-css-variables": "0.9.33",
|
||||
"camel-case": "4.1.2",
|
||||
"date-fns": "2.30.0",
|
||||
"date-fns": "3.2.0",
|
||||
"dayjs": "1.11.10",
|
||||
"dompurify": "3.0.6",
|
||||
"dompurify": "3.0.8",
|
||||
"fast-deep-equal": "3.1.3",
|
||||
"flatpickr": "4.6.13",
|
||||
"flexsearch": "0.7.31",
|
||||
"floating-vue": "2.0.0-beta.24",
|
||||
"floating-vue": "5.0.3",
|
||||
"is-touch-device": "1.0.1",
|
||||
"klona": "2.0.6",
|
||||
"lodash.debounce": "4.0.8",
|
||||
|
@ -113,17 +113,17 @@
|
|||
"sortablejs": "1.15.1",
|
||||
"tippy.js": "6.3.7",
|
||||
"ufo": "1.3.2",
|
||||
"vue": "3.3.13",
|
||||
"vue": "3.4.8",
|
||||
"vue-advanced-cropper": "2.8.8",
|
||||
"vue-flatpickr-component": "11.0.3",
|
||||
"vue-i18n": "9.8.0",
|
||||
"vue-i18n": "9.9.0",
|
||||
"vue-router": "4.2.5",
|
||||
"workbox-precaching": "7.0.0",
|
||||
"zhyswan-vuedraggable": "4.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@4tw/cypress-drag-drop": "2.2.5",
|
||||
"@cypress/vite-dev-server": "5.0.6",
|
||||
"@cypress/vite-dev-server": "5.0.7",
|
||||
"@cypress/vue": "6.0.0",
|
||||
"@faker-js/faker": "8.3.1",
|
||||
"@histoire/plugin-screenshot": "0.17.6",
|
||||
|
@ -136,44 +136,44 @@
|
|||
"@types/is-touch-device": "1.0.2",
|
||||
"@types/lodash.debounce": "4.0.9",
|
||||
"@types/marked": "5.0.2",
|
||||
"@types/node": "20.10.5",
|
||||
"@types/node": "20.10.8",
|
||||
"@types/postcss-preset-env": "7.7.0",
|
||||
"@types/sortablejs": "1.15.7",
|
||||
"@typescript-eslint/eslint-plugin": "6.15.0",
|
||||
"@typescript-eslint/parser": "6.15.0",
|
||||
"@typescript-eslint/eslint-plugin": "6.18.1",
|
||||
"@typescript-eslint/parser": "6.18.1",
|
||||
"@vitejs/plugin-legacy": "5.2.0",
|
||||
"@vitejs/plugin-vue": "4.5.2",
|
||||
"@vitejs/plugin-vue": "4.6.2",
|
||||
"@vue/eslint-config-typescript": "12.0.0",
|
||||
"@vue/test-utils": "2.4.3",
|
||||
"@vue/tsconfig": "0.5.1",
|
||||
"autoprefixer": "10.4.16",
|
||||
"browserslist": "4.22.2",
|
||||
"caniuse-lite": "1.0.30001570",
|
||||
"caniuse-lite": "1.0.30001576",
|
||||
"css-has-pseudo": "6.0.1",
|
||||
"csstype": "3.1.3",
|
||||
"cypress": "13.6.1",
|
||||
"esbuild": "0.19.10",
|
||||
"cypress": "13.6.2",
|
||||
"esbuild": "0.19.11",
|
||||
"eslint": "8.56.0",
|
||||
"eslint-plugin-vue": "9.19.2",
|
||||
"happy-dom": "12.10.3",
|
||||
"histoire": "0.17.6",
|
||||
"postcss": "8.4.32",
|
||||
"postcss": "8.4.33",
|
||||
"postcss-easing-gradients": "3.0.1",
|
||||
"postcss-easings": "4.0.0",
|
||||
"postcss-focus-within": "8.0.1",
|
||||
"postcss-preset-env": "9.3.0",
|
||||
"rollup": "4.9.1",
|
||||
"rollup-plugin-visualizer": "5.11.0",
|
||||
"sass": "1.69.5",
|
||||
"rollup": "4.9.4",
|
||||
"rollup-plugin-visualizer": "5.12.0",
|
||||
"sass": "1.69.7",
|
||||
"start-server-and-test": "2.0.3",
|
||||
"typescript": "5.3.3",
|
||||
"vite": "5.0.10",
|
||||
"vite": "5.0.11",
|
||||
"vite-plugin-inject-preload": "1.3.3",
|
||||
"vite-plugin-pwa": "0.17.4",
|
||||
"vite-plugin-sentry": "1.3.0",
|
||||
"vite-svg-loader": "5.1.0",
|
||||
"vitest": "1.0.4",
|
||||
"vue-tsc": "1.8.25",
|
||||
"vitest": "1.1.3",
|
||||
"vue-tsc": "1.8.27",
|
||||
"wait-on": "7.2.0",
|
||||
"workbox-cli": "7.0.0"
|
||||
},
|
||||
|
|
1797
pnpm-lock.yaml
1797
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
|
@ -81,9 +81,8 @@ import Popup from '@/components/misc/popup.vue'
|
|||
import {DATE_RANGES} from '@/components/date/dateRanges'
|
||||
import BaseButton from '@/components/base/BaseButton.vue'
|
||||
import DatemathHelp from '@/components/date/datemathHelp.vue'
|
||||
import {useAuthStore} from '@/stores/auth'
|
||||
import { getFlatpickrLanguage } from '@/helpers/flatpickrLanguage'
|
||||
|
||||
const authStore = useAuthStore()
|
||||
const {t} = useI18n({useScope: 'global'})
|
||||
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
|
@ -93,8 +92,6 @@ const props = defineProps({
|
|||
},
|
||||
})
|
||||
|
||||
// FIXME: This seems to always contain the default value - that breaks the picker
|
||||
const weekStart = computed(() => authStore.settings.weekStart ?? 0)
|
||||
const flatPickerConfig = computed(() => ({
|
||||
altFormat: t('date.altFormatLong'),
|
||||
altInput: true,
|
||||
|
@ -102,9 +99,7 @@ const flatPickerConfig = computed(() => ({
|
|||
enableTime: false,
|
||||
wrap: true,
|
||||
mode: 'range',
|
||||
locale: {
|
||||
firstDayOf7Days: weekStart.value,
|
||||
},
|
||||
locale: getFlatpickrLanguage(),
|
||||
}))
|
||||
|
||||
const showHowItWorks = ref(false)
|
||||
|
|
|
@ -80,8 +80,8 @@ import {formatDate} from '@/helpers/time/formatDate'
|
|||
import {calculateDayInterval} from '@/helpers/time/calculateDayInterval'
|
||||
import {calculateNearestHours} from '@/helpers/time/calculateNearestHours'
|
||||
import {createDateFromString} from '@/helpers/time/createDateFromString'
|
||||
import {useAuthStore} from '@/stores/auth'
|
||||
import {useI18n} from 'vue-i18n'
|
||||
import { getFlatpickrLanguage } from '@/helpers/flatpickrLanguage'
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
|
@ -105,8 +105,6 @@ watch(
|
|||
{immediate: true},
|
||||
)
|
||||
|
||||
const authStore = useAuthStore()
|
||||
const weekStart = computed(() => authStore.settings.weekStart)
|
||||
const flatPickerConfig = computed(() => ({
|
||||
altFormat: t('date.altFormatLong'),
|
||||
altInput: true,
|
||||
|
@ -114,9 +112,7 @@ const flatPickerConfig = computed(() => ({
|
|||
enableTime: true,
|
||||
time_24hr: true,
|
||||
inline: true,
|
||||
locale: {
|
||||
firstDayOfWeek: weekStart.value,
|
||||
},
|
||||
locale: getFlatpickrLanguage(),
|
||||
}))
|
||||
|
||||
// Since flatpickr dates are strings, we need to convert them to native date objects.
|
||||
|
@ -128,6 +124,10 @@ const flatPickrDate = computed({
|
|||
return
|
||||
}
|
||||
|
||||
const oldDate = formatDate(date.value, 'yyy-LL-dd H:mm')
|
||||
if (oldDate !== newValue) {
|
||||
return
|
||||
}
|
||||
date.value = createDateFromString(newValue)
|
||||
updateData()
|
||||
},
|
||||
|
@ -155,10 +155,6 @@ function updateData() {
|
|||
}
|
||||
|
||||
function setDate(dateString: string) {
|
||||
if (date.value === null) {
|
||||
date.value = new Date()
|
||||
}
|
||||
|
||||
const interval = calculateDayInterval(dateString)
|
||||
const newDate = new Date()
|
||||
newDate.setDate(newDate.getDate() + interval)
|
||||
|
@ -166,7 +162,6 @@ function setDate(dateString: string) {
|
|||
newDate.setMinutes(0)
|
||||
newDate.setSeconds(0)
|
||||
date.value = newDate
|
||||
flatPickrDate.value = newDate
|
||||
updateData()
|
||||
}
|
||||
|
||||
|
|
|
@ -61,6 +61,8 @@ import {
|
|||
import Loading from '@/components/misc/loading.vue'
|
||||
import {MILLISECONDS_A_DAY} from '@/constants/date'
|
||||
import {useWeekDayFromDate} from '@/helpers/time/formatDate'
|
||||
import dayjs from 'dayjs'
|
||||
import {useDayjsLanguageSync} from '@/i18n/useDayjsLanguageSync'
|
||||
|
||||
export interface GanttChartProps {
|
||||
isLoading: boolean,
|
||||
|
@ -81,8 +83,8 @@ const emit = defineEmits<{
|
|||
const {tasks, filters} = toRefs(props)
|
||||
|
||||
// setup dayjs for vue-ganttastic
|
||||
const dayjsLanguageLoading = ref(false)
|
||||
// const dayjsLanguageLoading = useDayjsLanguageSync(dayjs)
|
||||
// const dayjsLanguageLoading = ref(false)
|
||||
const dayjsLanguageLoading = useDayjsLanguageSync(dayjs)
|
||||
extendDayjs()
|
||||
|
||||
const ganttContainer = ref(null)
|
||||
|
|
|
@ -44,7 +44,7 @@ import flatPickr from 'vue-flatpickr-component'
|
|||
|
||||
import TaskService from '@/services/task'
|
||||
import type {ITask} from '@/modelTypes/ITask'
|
||||
import {useAuthStore} from '@/stores/auth'
|
||||
import { getFlatpickrLanguage } from '@/helpers/flatpickrLanguage'
|
||||
|
||||
const {
|
||||
modelValue,
|
||||
|
@ -55,7 +55,6 @@ const {
|
|||
const emit = defineEmits(['update:modelValue'])
|
||||
|
||||
const {t} = useI18n({useScope: 'global'})
|
||||
const authStore = useAuthStore()
|
||||
|
||||
const taskService = shallowReactive(new TaskService())
|
||||
const task = ref<ITask>()
|
||||
|
@ -102,9 +101,7 @@ const flatPickerConfig = computed(() => ({
|
|||
enableTime: true,
|
||||
time_24hr: true,
|
||||
inline: true,
|
||||
locale: {
|
||||
firstDayOfWeek: authStore.settings.weekStart,
|
||||
},
|
||||
locale: getFlatpickrLanguage(),
|
||||
}))
|
||||
|
||||
function deferDays(days: number) {
|
||||
|
|
15
src/helpers/flatpickrLanguage.ts
Normal file
15
src/helpers/flatpickrLanguage.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import {useAuthStore} from '@/stores/auth'
|
||||
import FlatpickrLanguages from 'flatpickr/dist/l10n'
|
||||
import type { CustomLocale, key } from 'flatpickr/dist/types/locale'
|
||||
|
||||
export function getFlatpickrLanguage(): CustomLocale {
|
||||
const authStore = useAuthStore()
|
||||
const lang = authStore.settings.language
|
||||
const langPair = lang.split('-')
|
||||
let language = FlatpickrLanguages[lang === 'vi-vn' ? 'vn' : 'en']
|
||||
if (langPair.length > 0 && FlatpickrLanguages[langPair[0] as key] !== undefined) {
|
||||
language = FlatpickrLanguages[langPair[0] as key]
|
||||
}
|
||||
language.firstDayOfWeek = authStore.settings.weekStart ?? language.firstDayOfWeek
|
||||
return language
|
||||
}
|
|
@ -15,34 +15,32 @@ interface dateFoundResult {
|
|||
const monthsRegexGroup = '(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)'
|
||||
|
||||
function matchesDateExpr(text: string, dateExpr: string): boolean {
|
||||
return text.match(new RegExp('(^| )' + dateExpr, 'g')) !== null
|
||||
return text.match(new RegExp('(^| )' + dateExpr, 'gi')) !== null
|
||||
}
|
||||
|
||||
export const parseDate = (text: string, now: Date = new Date()): dateParseResult => {
|
||||
const lowerText: string = text.toLowerCase()
|
||||
|
||||
if (matchesDateExpr(lowerText, 'today')) {
|
||||
if (matchesDateExpr(text, 'today')) {
|
||||
return addTimeToDate(text, getDateFromInterval(calculateDayInterval('today')), 'today')
|
||||
}
|
||||
if (matchesDateExpr(lowerText, 'tomorrow')) {
|
||||
if (matchesDateExpr(text, 'tomorrow')) {
|
||||
return addTimeToDate(text, getDateFromInterval(calculateDayInterval('tomorrow')), 'tomorrow')
|
||||
}
|
||||
if (matchesDateExpr(lowerText, 'next monday')) {
|
||||
if (matchesDateExpr(text, 'next monday')) {
|
||||
return addTimeToDate(text, getDateFromInterval(calculateDayInterval('nextMonday')), 'next monday')
|
||||
}
|
||||
if (matchesDateExpr(lowerText, 'this weekend')) {
|
||||
if (matchesDateExpr(text, 'this weekend')) {
|
||||
return addTimeToDate(text, getDateFromInterval(calculateDayInterval('thisWeekend')), 'this weekend')
|
||||
}
|
||||
if (matchesDateExpr(lowerText, 'later this week')) {
|
||||
if (matchesDateExpr(text, 'later this week')) {
|
||||
return addTimeToDate(text, getDateFromInterval(calculateDayInterval('laterThisWeek')), 'later this week')
|
||||
}
|
||||
if (matchesDateExpr(lowerText, 'later next week')) {
|
||||
if (matchesDateExpr(text, 'later next week')) {
|
||||
return addTimeToDate(text, getDateFromInterval(calculateDayInterval('laterNextWeek')), 'later next week')
|
||||
}
|
||||
if (matchesDateExpr(lowerText, 'next week')) {
|
||||
if (matchesDateExpr(text, 'next week')) {
|
||||
return addTimeToDate(text, getDateFromInterval(calculateDayInterval('nextWeek')), 'next week')
|
||||
}
|
||||
if (matchesDateExpr(lowerText, 'next month')) {
|
||||
if (matchesDateExpr(text, 'next month')) {
|
||||
const date: Date = new Date()
|
||||
date.setDate(1)
|
||||
date.setMonth(date.getMonth() + 1)
|
||||
|
@ -52,7 +50,7 @@ export const parseDate = (text: string, now: Date = new Date()): dateParseResult
|
|||
|
||||
return addTimeToDate(text, date, 'next month')
|
||||
}
|
||||
if (matchesDateExpr(lowerText, 'end of month')) {
|
||||
if (matchesDateExpr(text, 'end of month')) {
|
||||
const curDate: Date = new Date()
|
||||
const date: Date = new Date(curDate.getFullYear(), curDate.getMonth() + 1, 0)
|
||||
date.setHours(calculateNearestHours(date))
|
||||
|
@ -70,7 +68,7 @@ export const parseDate = (text: string, now: Date = new Date()): dateParseResult
|
|||
parsed = getDayFromText(text)
|
||||
if (parsed.date !== null) {
|
||||
const month = getMonthFromText(text, parsed.date)
|
||||
return addTimeToDate(text, month.date, parsed.foundText)
|
||||
return addTimeToDate(month.newText, month.date, parsed.foundText)
|
||||
}
|
||||
|
||||
parsed = getDateFromTextIn(text, now)
|
||||
|
@ -123,7 +121,7 @@ const addTimeToDate = (text: string, date: Date, previousMatch: string | null):
|
|||
|
||||
const replace = results !== null ? results[0] : previousMatch
|
||||
return {
|
||||
newText: replaceAll(text, replace, ''),
|
||||
newText: replaceAll(text, replace, '').trim(),
|
||||
date: date,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -160,6 +160,7 @@
|
|||
"expired": "انتهت صلاحية هذا الرمز {ago}.",
|
||||
"tokenCreatedSuccess": "إليك رمز Api الجديد: {token}",
|
||||
"tokenCreatedNotSeeAgain": "قم بتخزينه في مكان آمن، لن تتمكن من عرضه مرة أخرى!",
|
||||
"selectAll": "Select all",
|
||||
"delete": {
|
||||
"header": "احذف هذا الرمز",
|
||||
"text1": "هل أنت متأكد من رغبتك في حذف الرمز \"{token}؟",
|
||||
|
|
|
@ -160,6 +160,7 @@
|
|||
"expired": "This token has expired {ago}.",
|
||||
"tokenCreatedSuccess": "Here is your new api token: {token}",
|
||||
"tokenCreatedNotSeeAgain": "Store it in a secure location, you won't see it again!",
|
||||
"selectAll": "Select all",
|
||||
"delete": {
|
||||
"header": "Delete this token",
|
||||
"text1": "Are you sure you want to delete the token \"{token}\"?",
|
||||
|
|
|
@ -160,6 +160,7 @@
|
|||
"expired": "Platnost tohoto tokenu vypršela {ago}.",
|
||||
"tokenCreatedSuccess": "Zde je tvůj nový api token: {token}",
|
||||
"tokenCreatedNotSeeAgain": "Ulož jej na zabezpečeném místě, už ho znovu neuvidíš!",
|
||||
"selectAll": "Označit vše",
|
||||
"delete": {
|
||||
"header": "Smazat tento token",
|
||||
"text1": "Opravdu chcete smazat token \"{token}\"?",
|
||||
|
|
|
@ -160,6 +160,7 @@
|
|||
"expired": "This token has expired {ago}.",
|
||||
"tokenCreatedSuccess": "Here is your new api token: {token}",
|
||||
"tokenCreatedNotSeeAgain": "Store it in a secure location, you won't see it again!",
|
||||
"selectAll": "Select all",
|
||||
"delete": {
|
||||
"header": "Delete this token",
|
||||
"text1": "Are you sure you want to delete the token \"{token}\"?",
|
||||
|
|
|
@ -160,6 +160,7 @@
|
|||
"expired": "Dieses Token ist {ago} abgelaufen.",
|
||||
"tokenCreatedSuccess": "Hier ist dein neues API Token: {token}",
|
||||
"tokenCreatedNotSeeAgain": "Speichere es an einem sicheren Ort, du wirst es nicht mehr sehen!",
|
||||
"selectAll": "Alle auswählen",
|
||||
"delete": {
|
||||
"header": "Dieses Token löschen",
|
||||
"text1": "Bist Du sicher, dass Du das Token \"{token}\" löschen möchtest?",
|
||||
|
@ -177,7 +178,7 @@
|
|||
"title": "Lösche deinen Vikunja-Account",
|
||||
"text1": "Das Löschen deines Accounts ist dauerhaft und unwiderruflich. Alle Projekte, Aufgaben und zugehörige Daten werden gelöscht.",
|
||||
"text2": "Zum Fortfahren gib bitte dein Passwort ein. Du erhältst eine E-Mail mit weiteren Anweisungen.",
|
||||
"text3": "To proceed, please press the button below. You will receive an email with further instructions.",
|
||||
"text3": "Klicks zum Fortfahren auf den Button unten. Du erhältst eine E-Mail mit weiteren Anweisungen.",
|
||||
"confirm": "Meinen Account löschen",
|
||||
"requestSuccess": "Die Anfrage war erfolgreich. Du erhältst eine E-Mail mit weiteren Anweisungen.",
|
||||
"passwordRequired": "Bitte gib dein Passwort ein.",
|
||||
|
@ -185,7 +186,7 @@
|
|||
"scheduled": "Wir werden deinen Vikunja-Account am {date} ({dateSince}) löschen.",
|
||||
"scheduledCancel": "Um die Löschung deines Accounts abzubrechen, klicke hier.",
|
||||
"scheduledCancelText": "Um die Löschung deines Accounts abzubrechen, gib bitte dein Passwort unten ein:",
|
||||
"scheduledCancelButton": "To cancel the deletion of your account, please press the button below:",
|
||||
"scheduledCancelButton": "Um die Löschung deines Accounts abzubrechen, klicke unten auf den Button:",
|
||||
"scheduledCancelConfirm": "Löschung meines Accounts abbrechen",
|
||||
"scheduledCancelSuccess": "Wir werden deinen Account nicht löschen."
|
||||
},
|
||||
|
@ -937,7 +938,7 @@
|
|||
"delete": "Diese Aufgabe löschen",
|
||||
"priority": "Die Priorität dieser Aufgabe ändern",
|
||||
"favorite": "Diese Aufgabe zum Favoriten machen / von Favoriten entfernen",
|
||||
"save": "Save the current task"
|
||||
"save": "Aktuelle Aufgabe speichern"
|
||||
},
|
||||
"project": {
|
||||
"title": "Projektansichten",
|
||||
|
|
|
@ -160,6 +160,7 @@
|
|||
"expired": "Dieses Token ist {ago} abgelaufen.",
|
||||
"tokenCreatedSuccess": "Hier ist dein neues API Token: {token}",
|
||||
"tokenCreatedNotSeeAgain": "Speichere es an einem sicheren Ort, du wirst es nicht mehr sehen!",
|
||||
"selectAll": "Alle auswählen",
|
||||
"delete": {
|
||||
"header": "Dieses Token löschen",
|
||||
"text1": "Bist Du sicher, dass Du das Token \"{token}\" löschen möchtest?",
|
||||
|
@ -177,7 +178,7 @@
|
|||
"title": "Lösche deinen Vikunja-Account",
|
||||
"text1": "Das Löschen deines Accounts ist dauerhaft und unwiderruflich. Alle Projekte, Aufgaben und zugehörige Daten werden gelöscht.",
|
||||
"text2": "Zum Fortfahren gib bitte dein Passwort ein. Du erhältst eine E-Mail mit weiteren Anweisungen.",
|
||||
"text3": "To proceed, please press the button below. You will receive an email with further instructions.",
|
||||
"text3": "Klicks zum Fortfahren auf den Button unten. Du erhältst eine E-Mail mit weiteren Anweisungen.",
|
||||
"confirm": "Meinen Account löschen",
|
||||
"requestSuccess": "Die Anfrage war erfolgreich. Du erhältst eine E-Mail mit weiteren Anweisungen.",
|
||||
"passwordRequired": "Bitte gib dein Passwort ein.",
|
||||
|
@ -185,7 +186,7 @@
|
|||
"scheduled": "Wir werden deinen Vikunja-Account am {date} ({dateSince}) löschen.",
|
||||
"scheduledCancel": "Um die Löschung deines Accounts abzubrechen, klicke hier.",
|
||||
"scheduledCancelText": "Um die Löschung deines Accounts abzubrechen, gib bitte dein Passwort unten ein:",
|
||||
"scheduledCancelButton": "To cancel the deletion of your account, please press the button below:",
|
||||
"scheduledCancelButton": "Um die Löschung deines Accounts abzubrechen, klicke unten auf den Button:",
|
||||
"scheduledCancelConfirm": "Löschung meines Accounts abbrechen",
|
||||
"scheduledCancelSuccess": "Wir werden deinen Account nicht löschen."
|
||||
},
|
||||
|
@ -937,7 +938,7 @@
|
|||
"delete": "Diese Aufgabe löschen",
|
||||
"priority": "Die Priorität dieser Aufgabe ändern",
|
||||
"favorite": "Diese Aufgabe zum Favoriten machen / von Favoriten entfernen",
|
||||
"save": "Save the current task"
|
||||
"save": "Aktuelle Aufgabe speichern"
|
||||
},
|
||||
"project": {
|
||||
"title": "Projektansichten",
|
||||
|
|
|
@ -160,6 +160,7 @@
|
|||
"expired": "This token has expired {ago}.",
|
||||
"tokenCreatedSuccess": "Here is your new api token: {token}",
|
||||
"tokenCreatedNotSeeAgain": "Store it in a secure location, you won't see it again!",
|
||||
"selectAll": "Select all",
|
||||
"delete": {
|
||||
"header": "Delete this token",
|
||||
"text1": "Are you sure you want to delete the token \"{token}\"?",
|
||||
|
|
|
@ -160,6 +160,7 @@
|
|||
"expired": "This token has expired {ago}.",
|
||||
"tokenCreatedSuccess": "Here is your new api token: {token}",
|
||||
"tokenCreatedNotSeeAgain": "Store it in a secure location, you won't see it again!",
|
||||
"selectAll": "Select all",
|
||||
"delete": {
|
||||
"header": "Delete this token",
|
||||
"text1": "Are you sure you want to delete the token \"{token}\"?",
|
||||
|
|
|
@ -160,6 +160,7 @@
|
|||
"expired": "This token has expired {ago}.",
|
||||
"tokenCreatedSuccess": "Here is your new api token: {token}",
|
||||
"tokenCreatedNotSeeAgain": "Store it in a secure location, you won't see it again!",
|
||||
"selectAll": "Select all",
|
||||
"delete": {
|
||||
"header": "Delete this token",
|
||||
"text1": "Are you sure you want to delete the token \"{token}\"?",
|
||||
|
|
|
@ -160,6 +160,7 @@
|
|||
"expired": "Ez a token lejárt {ago}.",
|
||||
"tokenCreatedSuccess": "Íme az új API tokenje: {token}",
|
||||
"tokenCreatedNotSeeAgain": "Tárolja el biztonságos helyen, többé nem fogja látni!",
|
||||
"selectAll": "Select all",
|
||||
"delete": {
|
||||
"header": "Token törlése",
|
||||
"text1": "Biztos benne, hogy törölni akarja ezt a tokent \"{token}\"?",
|
||||
|
|
|
@ -160,6 +160,7 @@
|
|||
"expired": "This token has expired {ago}.",
|
||||
"tokenCreatedSuccess": "Here is your new api token: {token}",
|
||||
"tokenCreatedNotSeeAgain": "Store it in a secure location, you won't see it again!",
|
||||
"selectAll": "Select all",
|
||||
"delete": {
|
||||
"header": "Delete this token",
|
||||
"text1": "Are you sure you want to delete the token \"{token}\"?",
|
||||
|
|
|
@ -160,6 +160,7 @@
|
|||
"expired": "This token has expired {ago}.",
|
||||
"tokenCreatedSuccess": "Here is your new api token: {token}",
|
||||
"tokenCreatedNotSeeAgain": "このトークンは二度と表示されません。安全な場所に保管してください。",
|
||||
"selectAll": "Select all",
|
||||
"delete": {
|
||||
"header": "トークンの削除",
|
||||
"text1": "Are you sure you want to delete the token \"{token}\"?",
|
||||
|
|
|
@ -160,6 +160,7 @@
|
|||
"expired": "This token has expired {ago}.",
|
||||
"tokenCreatedSuccess": "Here is your new api token: {token}",
|
||||
"tokenCreatedNotSeeAgain": "Store it in a secure location, you won't see it again!",
|
||||
"selectAll": "Select all",
|
||||
"delete": {
|
||||
"header": "Delete this token",
|
||||
"text1": "Are you sure you want to delete the token \"{token}\"?",
|
||||
|
|
|
@ -160,6 +160,7 @@
|
|||
"expired": "This token has expired {ago}.",
|
||||
"tokenCreatedSuccess": "Here is your new api token: {token}",
|
||||
"tokenCreatedNotSeeAgain": "Store it in a secure location, you won't see it again!",
|
||||
"selectAll": "Select all",
|
||||
"delete": {
|
||||
"header": "Delete this token",
|
||||
"text1": "Are you sure you want to delete the token \"{token}\"?",
|
||||
|
|
|
@ -160,6 +160,7 @@
|
|||
"expired": "This token has expired {ago}.",
|
||||
"tokenCreatedSuccess": "Here is your new api token: {token}",
|
||||
"tokenCreatedNotSeeAgain": "Store it in a secure location, you won't see it again!",
|
||||
"selectAll": "Select all",
|
||||
"delete": {
|
||||
"header": "Delete this token",
|
||||
"text1": "Are you sure you want to delete the token \"{token}\"?",
|
||||
|
|
|
@ -160,6 +160,7 @@
|
|||
"expired": "Ten token wygasł {ago}.",
|
||||
"tokenCreatedSuccess": "Oto twój nowy token: {token}",
|
||||
"tokenCreatedNotSeeAgain": "Przechowuj go w bezpiecznym miejscu, nie zobaczysz go ponownie!",
|
||||
"selectAll": "Wybierz wszystkie",
|
||||
"delete": {
|
||||
"header": "Usuń ten token",
|
||||
"text1": "Czy na pewno chcesz usunąć token \"{token}\"?",
|
||||
|
|
|
@ -160,6 +160,7 @@
|
|||
"expired": "This token has expired {ago}.",
|
||||
"tokenCreatedSuccess": "Here is your new api token: {token}",
|
||||
"tokenCreatedNotSeeAgain": "Store it in a secure location, you won't see it again!",
|
||||
"selectAll": "Select all",
|
||||
"delete": {
|
||||
"header": "Delete this token",
|
||||
"text1": "Are you sure you want to delete the token \"{token}\"?",
|
||||
|
|
|
@ -160,6 +160,7 @@
|
|||
"expired": "Este token expirou {ago}.",
|
||||
"tokenCreatedSuccess": "Aqui está o teu novo token de API: {token}",
|
||||
"tokenCreatedNotSeeAgain": "Guarda-o num local seguro, não o vais poder visualizar novamente!",
|
||||
"selectAll": "Selecionar tudo",
|
||||
"delete": {
|
||||
"header": "Eliminar este token",
|
||||
"text1": "Tens a certeza que pretendes eliminar o token \"{token}\"?",
|
||||
|
|
|
@ -160,6 +160,7 @@
|
|||
"expired": "This token has expired {ago}.",
|
||||
"tokenCreatedSuccess": "Here is your new api token: {token}",
|
||||
"tokenCreatedNotSeeAgain": "Store it in a secure location, you won't see it again!",
|
||||
"selectAll": "Select all",
|
||||
"delete": {
|
||||
"header": "Delete this token",
|
||||
"text1": "Are you sure you want to delete the token \"{token}\"?",
|
||||
|
|
|
@ -160,6 +160,7 @@
|
|||
"expired": "Срок действия этого токена истёк {ago}.",
|
||||
"tokenCreatedSuccess": "Ваш новый токен: {token}",
|
||||
"tokenCreatedNotSeeAgain": "Сохраните его в безопасном месте, вы не увидите его снова!",
|
||||
"selectAll": "Выбрать всё",
|
||||
"delete": {
|
||||
"header": "Удалить этот токен",
|
||||
"text1": "Удалить токен «{token}»?",
|
||||
|
|
|
@ -160,6 +160,7 @@
|
|||
"expired": "This token has expired {ago}.",
|
||||
"tokenCreatedSuccess": "Here is your new api token: {token}",
|
||||
"tokenCreatedNotSeeAgain": "Store it in a secure location, you won't see it again!",
|
||||
"selectAll": "Select all",
|
||||
"delete": {
|
||||
"header": "Delete this token",
|
||||
"text1": "Are you sure you want to delete the token \"{token}\"?",
|
||||
|
|
|
@ -160,6 +160,7 @@
|
|||
"expired": "Žeton je potekel pred {ago}.",
|
||||
"tokenCreatedSuccess": "Tu je vaš novi API žeton: {token}",
|
||||
"tokenCreatedNotSeeAgain": "Shranite ga na varno mesto, ker ga ne boste več videli!",
|
||||
"selectAll": "Izberi vse",
|
||||
"delete": {
|
||||
"header": "Izbriši ta žeton",
|
||||
"text1": "Ali ste prepričani, da želite izbrisati žeton \"{token}\"?",
|
||||
|
|
|
@ -160,6 +160,7 @@
|
|||
"expired": "This token has expired {ago}.",
|
||||
"tokenCreatedSuccess": "Here is your new api token: {token}",
|
||||
"tokenCreatedNotSeeAgain": "Store it in a secure location, you won't see it again!",
|
||||
"selectAll": "Select all",
|
||||
"delete": {
|
||||
"header": "Delete this token",
|
||||
"text1": "Are you sure you want to delete the token \"{token}\"?",
|
||||
|
|
|
@ -160,6 +160,7 @@
|
|||
"expired": "This token has expired {ago}.",
|
||||
"tokenCreatedSuccess": "Here is your new api token: {token}",
|
||||
"tokenCreatedNotSeeAgain": "Förvara den på en säker plats, du kommer aldrig att se den igen!",
|
||||
"selectAll": "Select all",
|
||||
"delete": {
|
||||
"header": "Delete this token",
|
||||
"text1": "Are you sure you want to delete the token \"{token}\"?",
|
||||
|
|
|
@ -160,6 +160,7 @@
|
|||
"expired": "This token has expired {ago}.",
|
||||
"tokenCreatedSuccess": "Here is your new api token: {token}",
|
||||
"tokenCreatedNotSeeAgain": "Store it in a secure location, you won't see it again!",
|
||||
"selectAll": "Select all",
|
||||
"delete": {
|
||||
"header": "Delete this token",
|
||||
"text1": "Are you sure you want to delete the token \"{token}\"?",
|
||||
|
|
|
@ -160,6 +160,7 @@
|
|||
"expired": "This token has expired {ago}.",
|
||||
"tokenCreatedSuccess": "Here is your new api token: {token}",
|
||||
"tokenCreatedNotSeeAgain": "Store it in a secure location, you won't see it again!",
|
||||
"selectAll": "Select all",
|
||||
"delete": {
|
||||
"header": "Delete this token",
|
||||
"text1": "Are you sure you want to delete the token \"{token}\"?",
|
||||
|
|
|
@ -5,17 +5,17 @@
|
|||
"welcomeDay": "嗨~,{username}!",
|
||||
"welcomeEvening": "中午好,{username}!",
|
||||
"lastViewed": "最近查看",
|
||||
"addToHomeScreen": "Add this app to your home screen for faster access and improved experience.",
|
||||
"goToOverview": "Go to overview",
|
||||
"addToHomeScreen": "将此应用程序添加到您的主屏幕以便更快地访问和改善体验。",
|
||||
"goToOverview": "转到概览",
|
||||
"project": {
|
||||
"importText": "Import your projects and tasks from other services into Vikunja:",
|
||||
"import": "Import your data into Vikunja"
|
||||
"importText": "将您的项目和任务从其他服务导入 Vikunja:",
|
||||
"import": "将您的数据导入到 Vikunja"
|
||||
}
|
||||
},
|
||||
"demo": {
|
||||
"title": "This instance is in demo mode. Do not use this for real data!",
|
||||
"everythingWillBeDeleted": "Everything will be deleted in regular intervals!",
|
||||
"accountWillBeDeleted": "Your account will be deleted, including all projects, tasks and attachments you might create."
|
||||
"title": "此实例处于演示模式。不要将其用于真实数据!",
|
||||
"everythingWillBeDeleted": "每隔一段时间,所有东西都将被删除!",
|
||||
"accountWillBeDeleted": "您的账户将被删除,包括您可能创建的所有项目、任务和附件。"
|
||||
},
|
||||
"404": {
|
||||
"title": "未找到数据",
|
||||
|
@ -83,17 +83,17 @@
|
|||
"savedSuccess": "成功更新了设置",
|
||||
"emailReminders": "通过电子邮件向我发送任务提醒",
|
||||
"overdueReminders": "每天给我发送我未完成任务的摘要",
|
||||
"discoverableByName": "Allow other users to add me as a member to teams or projects when they search for my name",
|
||||
"discoverableByEmail": "Allow other users to add me as a member to teams or projects when they search for my full email",
|
||||
"discoverableByName": "允许其他用户在搜索我的名字时将我添加为团队或项目的成员",
|
||||
"discoverableByEmail": "允许其他用户在搜索我的完整电子邮件时将我添加为团队或项目的成员",
|
||||
"playSoundWhenDone": "将任务标记为已完成时播放声音",
|
||||
"weekStart": "一周起始日",
|
||||
"weekStartSunday": "星期日",
|
||||
"weekStartMonday": "星期一",
|
||||
"language": "语言设置",
|
||||
"defaultProject": "Default Project",
|
||||
"defaultProject": "默认项目",
|
||||
"timezone": "时区",
|
||||
"overdueTasksRemindersTime": "逾期任务提醒邮件时间",
|
||||
"filterUsedOnOverview": "Saved filter used on the overview page"
|
||||
"filterUsedOnOverview": "概述页面上使用已保存过滤器"
|
||||
},
|
||||
"totp": {
|
||||
"title": "两步验证",
|
||||
|
@ -147,37 +147,38 @@
|
|||
}
|
||||
},
|
||||
"apiTokens": {
|
||||
"title": "API Tokens",
|
||||
"general": "API tokens allow you to use Vikunja's API without user credentials.",
|
||||
"apiDocs": "Check out the api docs",
|
||||
"createAToken": "Create a token",
|
||||
"createToken": "Create token",
|
||||
"30d": "30 Days",
|
||||
"60d": "60 Days",
|
||||
"90d": "90 Days",
|
||||
"permissionExplanation": "Permissions allow you to scope what an api token is allowed to do.",
|
||||
"titleRequired": "The title is required",
|
||||
"expired": "This token has expired {ago}.",
|
||||
"tokenCreatedSuccess": "Here is your new api token: {token}",
|
||||
"tokenCreatedNotSeeAgain": "Store it in a secure location, you won't see it again!",
|
||||
"title": "API 令牌",
|
||||
"general": "API 令牌允许您在无需用户凭据的情况下使用 Vikunja 的 API。",
|
||||
"apiDocs": "查看 api 文档",
|
||||
"createAToken": "创建令牌",
|
||||
"createToken": "创建令牌",
|
||||
"30d": "30 天",
|
||||
"60d": "60 天",
|
||||
"90d": "90 天",
|
||||
"permissionExplanation": "权限允许您限制 api 令牌被允许做什么。",
|
||||
"titleRequired": "需要指定标题",
|
||||
"expired": "Token {ago} 前到期",
|
||||
"tokenCreatedSuccess": "这是您的令牌: {token}",
|
||||
"tokenCreatedNotSeeAgain": "将其存储在一个安全的位置,你不会再看到它了!",
|
||||
"selectAll": "全选",
|
||||
"delete": {
|
||||
"header": "Delete this token",
|
||||
"text1": "Are you sure you want to delete the token \"{token}\"?",
|
||||
"text2": "This will revoke access to all applications or integrations using it. You cannot undo this."
|
||||
"header": "删除该令牌",
|
||||
"text1": "你确定要删除令牌 {token} 吗?",
|
||||
"text2": "这将撤销使用它的所有应用程序或集成的访问权。您不能回退此操作。"
|
||||
},
|
||||
"attributes": {
|
||||
"title": "Title",
|
||||
"titlePlaceholder": "Enter a title you will recognize later",
|
||||
"expiresAt": "Expires at",
|
||||
"permissions": "Permissions"
|
||||
"title": "标题",
|
||||
"titlePlaceholder": "输入一个你以后能够识别的标题",
|
||||
"expiresAt": "过期于",
|
||||
"permissions": "权限"
|
||||
}
|
||||
}
|
||||
},
|
||||
"deletion": {
|
||||
"title": "删除您的 Vikunja 帐户",
|
||||
"text1": "The deletion of your account is permanent and cannot be undone. We will delete all your projects, tasks and everything associated with it.",
|
||||
"text1": "您账户的删除是永久性的且无法撤消。 我们将删除您的所有项目、任务以及与之相关的所有内容。",
|
||||
"text2": "若要继续,请输入您的密码。您将收到一封包含更多说明的电子邮件。",
|
||||
"text3": "To proceed, please press the button below. You will receive an email with further instructions.",
|
||||
"text3": "若要继续,请按下面的按钮。您将收到一封包含进一步说明的电子邮件。",
|
||||
"confirm": "删除我的帐户",
|
||||
"requestSuccess": "请求成功。您将收到一封包含更多说明的电子邮件。",
|
||||
"passwordRequired": "请输入密码",
|
||||
|
@ -185,13 +186,13 @@
|
|||
"scheduled": "您的 Vikunja帐户将于 {date} ({dateSince}) 完成注销删除。",
|
||||
"scheduledCancel": "要取消您的帐户删除操作,请单击此处。",
|
||||
"scheduledCancelText": "若要取消您的帐户删除操作,请在下面输入您的密码:",
|
||||
"scheduledCancelButton": "To cancel the deletion of your account, please press the button below:",
|
||||
"scheduledCancelButton": "若要取消您的账户删除,请按下面的按钮:",
|
||||
"scheduledCancelConfirm": "取消删除我的帐户",
|
||||
"scheduledCancelSuccess": "账户删除操作已撤销"
|
||||
},
|
||||
"export": {
|
||||
"title": "导出 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.",
|
||||
"description": "您可以索取所有 Vikunja 数据的副本。 这包括项目、任务以及与它们相关的所有内容。 您可以通过迁移功能将这些数据导入到任何 Vikunja 实例中。",
|
||||
"descriptionPasswordRequired": "请输入您的密码以继续。",
|
||||
"request": "请求我的 Vikunja 数据副本",
|
||||
"success": "已成功请求您的 Vikunja 数据!一旦准备好下载,我们将向您发送一封电子邮件。",
|
||||
|
@ -199,182 +200,182 @@
|
|||
}
|
||||
},
|
||||
"project": {
|
||||
"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",
|
||||
"color": "Color",
|
||||
"projects": "Projects",
|
||||
"parent": "Parent Project",
|
||||
"search": "Type to search for a project…",
|
||||
"searchSelect": "Click or press enter to select this project",
|
||||
"shared": "Shared Projects",
|
||||
"noDescriptionAvailable": "No project description is available.",
|
||||
"inboxTitle": "Inbox",
|
||||
"archivedMessage": "该项目已存档。 无法为其创建新任务或编辑任务。",
|
||||
"archived": "已归档",
|
||||
"showArchived": "显示已归档",
|
||||
"title": "项目标题",
|
||||
"color": "颜色",
|
||||
"projects": "项目",
|
||||
"parent": "父项目",
|
||||
"search": "输入以搜索项目…",
|
||||
"searchSelect": "点击或按下回车键以选择此项目",
|
||||
"shared": "共享项目",
|
||||
"noDescriptionAvailable": "没有可用的项目描述。",
|
||||
"inboxTitle": "收件箱",
|
||||
"create": {
|
||||
"header": "New project",
|
||||
"titlePlaceholder": "The project's title goes here…",
|
||||
"addTitleRequired": "Please specify a title.",
|
||||
"createdSuccess": "The project was successfully created.",
|
||||
"addProjectRequired": "Please specify a project or set a default project in the settings."
|
||||
"header": "新项目",
|
||||
"titlePlaceholder": "项目标题",
|
||||
"addTitleRequired": "请指定一个标题。",
|
||||
"createdSuccess": "已成功创建此项目。",
|
||||
"addProjectRequired": "请指定列表或在设置中设置默认列表。"
|
||||
},
|
||||
"archive": {
|
||||
"title": "Archive \"{project}\"",
|
||||
"archive": "Archive this project",
|
||||
"unarchive": "Un-Archive this project",
|
||||
"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.",
|
||||
"success": "The project was successfully archived."
|
||||
"title": "存档 \"{project}\"",
|
||||
"archive": "存档此项目",
|
||||
"unarchive": "取消存档此项目",
|
||||
"unarchiveText": "您将能够创建新任务或编辑此项目",
|
||||
"archiveText": "在您取消归档之前,您将无法编辑此项目或创建新任务。",
|
||||
"success": "项目已成功归档。"
|
||||
},
|
||||
"background": {
|
||||
"title": "Set project 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!"
|
||||
"title": "设置项目背景",
|
||||
"remove": "删除背景",
|
||||
"upload": "从您的pc选择背景",
|
||||
"searchPlaceholder": "搜索背景…",
|
||||
"poweredByUnsplash": "由 Unsplash 提供技术支持",
|
||||
"loadMore": "加载更多照片",
|
||||
"success": "背景图设置成功",
|
||||
"removeSuccess": "已移除背景"
|
||||
},
|
||||
"delete": {
|
||||
"title": "Delete \"{project}\"",
|
||||
"header": "Delete this project",
|
||||
"text1": "Are you sure you want to delete this project and all of its contents?",
|
||||
"text2": "This includes all tasks and CANNOT BE UNDONE!",
|
||||
"success": "The project was successfully deleted.",
|
||||
"tasksToDelete": "This will irrevocably remove approx. {count} tasks.",
|
||||
"noTasksToDelete": "This project does not contain any tasks, it should be safe to delete."
|
||||
"title": "删除\"{project}\"",
|
||||
"header": "删除此项目",
|
||||
"text1": "确认删除此项目及其所有任务?",
|
||||
"text2": "这包括所有的任务,并且无法撤销!",
|
||||
"success": "项目已成功删除。",
|
||||
"tasksToDelete": "此操作无法撤消!将移除大约 {count} 个任务。",
|
||||
"noTasksToDelete": "此列表不包含任何任务,可以安全删除。"
|
||||
},
|
||||
"duplicate": {
|
||||
"title": "Duplicate this project",
|
||||
"label": "Duplicate",
|
||||
"text": "Select a parent project which should hold the duplicated project:",
|
||||
"success": "The project was successfully duplicated."
|
||||
"title": "复制此项目",
|
||||
"label": "复制",
|
||||
"text": "选择一个已存在的命名空间以容纳该列表的副本",
|
||||
"success": "项目已成功复制."
|
||||
},
|
||||
"edit": {
|
||||
"header": "Edit This Project",
|
||||
"title": "Edit \"{project}\"",
|
||||
"titlePlaceholder": "The project title goes here…",
|
||||
"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",
|
||||
"identifierPlaceholder": "The project identifier goes here…",
|
||||
"description": "Description",
|
||||
"descriptionPlaceholder": "Enter a description for this project, hit '/' for more options…",
|
||||
"color": "Color",
|
||||
"success": "The project was successfully updated."
|
||||
"header": "编辑此项目",
|
||||
"title": "编辑 \"{project}\"",
|
||||
"titlePlaceholder": "项目标题位于此处",
|
||||
"identifierTooltip": "项目标识符可以用来独特识别整个项目的任务。您可以设置为空以禁用它。",
|
||||
"identifier": "项目标识符",
|
||||
"identifierPlaceholder": "项目标题位于此处",
|
||||
"description": "描述",
|
||||
"descriptionPlaceholder": "输入此项目的描述,点击'/'获取更多选项…",
|
||||
"color": "颜色",
|
||||
"success": "项目更新成功。"
|
||||
},
|
||||
"share": {
|
||||
"header": "Share this project",
|
||||
"title": "Share \"{project}\"",
|
||||
"share": "Share",
|
||||
"header": "共享项目",
|
||||
"title": "共享 \"{project}\"",
|
||||
"share": "共享",
|
||||
"links": {
|
||||
"title": "Share Links",
|
||||
"what": "What is a share link?",
|
||||
"explanation": "Share Links allow you to easily share a project 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 signing in, 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 project with this link share. This cannot be undone!",
|
||||
"createSuccess": "The link share was successfully created.",
|
||||
"deleteSuccess": "The link share was successfully deleted",
|
||||
"view": "View",
|
||||
"sharedBy": "Shared by {0}"
|
||||
"title": "共享链接",
|
||||
"what": "什么是共享链接?",
|
||||
"explanation": "共享链接使您能够轻松地与其他未注册账户的访客共享一个列表。",
|
||||
"create": "创建一个新的共享链接",
|
||||
"name": "共享链接名称 (可选)",
|
||||
"namePlaceholder": "例如:Lorem Ipsum",
|
||||
"nameExplanation": "此共享链接中的所有动作都将显示该名称。",
|
||||
"password": "密码 (可选)",
|
||||
"passwordExplanation": "验证时,用户需要输入此密码。",
|
||||
"noName": "未设置名称",
|
||||
"remove": "删除链接共享",
|
||||
"removeText": "您确定要删除此链接共享吗?它将无法使用此链接共享访问此项目。 这不能撤消!",
|
||||
"createSuccess": "列表共享链接成功创建。",
|
||||
"deleteSuccess": "共享链接已删除",
|
||||
"view": "查看",
|
||||
"sharedBy": "{0} 分享"
|
||||
},
|
||||
"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."
|
||||
"typeUser": "用户名 | 用户",
|
||||
"typeTeam": "团队 | 团队",
|
||||
"shared": "与 {type} 共享",
|
||||
"you": "您",
|
||||
"notShared": "尚未与任何 {type} 共享。",
|
||||
"removeHeader": "从 {sharable} 中移除一个 {type}",
|
||||
"removeText": "确定要将 {sharable} 从 {type} 中删除吗?此操作无法撤销。",
|
||||
"removeSuccess": "已成功将 {sharable} 从 {type} 中移除",
|
||||
"addedSuccess": "{type} 已成功添加。",
|
||||
"updatedSuccess": "{type} 已成功添加。"
|
||||
},
|
||||
"right": {
|
||||
"title": "Permission",
|
||||
"read": "Read only",
|
||||
"readWrite": "Read & write",
|
||||
"admin": "Admin"
|
||||
"title": "权限",
|
||||
"read": "只读",
|
||||
"readWrite": "可读并可写",
|
||||
"admin": "管理员"
|
||||
},
|
||||
"attributes": {
|
||||
"link": "Link",
|
||||
"delete": "Delete"
|
||||
"link": "链接",
|
||||
"delete": "删除"
|
||||
}
|
||||
},
|
||||
"list": {
|
||||
"title": "List",
|
||||
"add": "Add",
|
||||
"addPlaceholder": "Add a new task…",
|
||||
"empty": "This project is currently empty.",
|
||||
"newTaskCta": "Create a new task.",
|
||||
"editTask": "Edit Task"
|
||||
"title": "列表",
|
||||
"add": "添加",
|
||||
"addPlaceholder": "添加新任务",
|
||||
"empty": "此项目目前为空。",
|
||||
"newTaskCta": "新建任务。",
|
||||
"editTask": "编辑任务"
|
||||
},
|
||||
"gantt": {
|
||||
"title": "Gantt",
|
||||
"showTasksWithoutDates": "Show tasks which don't have dates set",
|
||||
"size": "Size",
|
||||
"default": "Default",
|
||||
"month": "Month",
|
||||
"day": "Day",
|
||||
"hour": "Hour",
|
||||
"range": "Date Range",
|
||||
"noDates": "This task has no dates set."
|
||||
"title": "甘特图",
|
||||
"showTasksWithoutDates": "显示未设定日期的任务",
|
||||
"size": "时间粒度",
|
||||
"default": "默认",
|
||||
"month": "月",
|
||||
"day": "日",
|
||||
"hour": "时",
|
||||
"range": "日期范围",
|
||||
"noDates": "此任务没有设定日期。"
|
||||
},
|
||||
"table": {
|
||||
"title": "Table",
|
||||
"columns": "Columns"
|
||||
"title": "表格",
|
||||
"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.",
|
||||
"defaultBucket": "Default bucket",
|
||||
"defaultBucketHint": "When creating tasks without specifying a bucket, they will be added to this bucket.",
|
||||
"defaultBucketSavedSuccess": "The default 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"
|
||||
"title": "看板",
|
||||
"limit": "限制: {limit}",
|
||||
"noLimit": "未设置",
|
||||
"doneBucket": "已完成的桶数",
|
||||
"doneBucketHint": "移入此存储桶的所有任务将自动标记为已完成。",
|
||||
"doneBucketHintExtended": "所有移入已完成存储桶的任务都将自动标记为已完成。 从其他位置标记为已完成的任务也将被移动。",
|
||||
"doneBucketSavedSuccess": "已完成存储桶已保存成功。",
|
||||
"defaultBucket": "默认桶",
|
||||
"defaultBucketHint": "当创建任务时没有指定一个桶,它们将被添加到此桶中。",
|
||||
"defaultBucketSavedSuccess": "默认存储桶已成功保存。",
|
||||
"deleteLast": "无法删除最后一个存储桶。",
|
||||
"addTaskPlaceholder": "输入新任务标题…",
|
||||
"addTask": "添加任务",
|
||||
"addAnotherTask": "添加另一个任务",
|
||||
"addBucket": "创建一个新的存储桶。",
|
||||
"addBucketPlaceholder": "输入新的存储桶标题…",
|
||||
"deleteHeaderBucket": "删除存储桶",
|
||||
"deleteBucketText1": "您确定要删除此存储桶吗?",
|
||||
"deleteBucketText2": "这不会删除任何任务,而是将其移动到默认存储桶中。",
|
||||
"deleteBucketSuccess": "存储桶已删除。",
|
||||
"bucketTitleSavedSuccess": "存储桶标题已保存。",
|
||||
"bucketLimitSavedSuccess": "存储桶限制已保存。",
|
||||
"collapse": "折叠此存储桶"
|
||||
},
|
||||
"pseudo": {
|
||||
"favorites": {
|
||||
"title": "Favorites"
|
||||
"title": "收藏"
|
||||
}
|
||||
},
|
||||
"webhooks": {
|
||||
"title": "Webhooks",
|
||||
"targetUrl": "Target URL",
|
||||
"targetUrlInvalid": "Please provide a valid URL.",
|
||||
"events": "Events",
|
||||
"eventsHint": "Select all events this webhook should recieve updates for (within the current project).",
|
||||
"mustSelectEvents": "You must select at least one event.",
|
||||
"delete": "Delete this webhook",
|
||||
"deleteText": "Are you sure you want to delete this webhook? External targets will not be notified of its events anymore.",
|
||||
"deleteSuccess": "The webhook was successfully deleted.",
|
||||
"create": "Create webhook",
|
||||
"secret": "Secret",
|
||||
"secretHint": "If provided, all requests to the webhook target URL will be signed using HMAC.",
|
||||
"secretDocs": "Check out the docs for more details about how to use secrets."
|
||||
"title": "Webhook",
|
||||
"targetUrl": "目标 Url",
|
||||
"targetUrlInvalid": "请提供有效的URL。",
|
||||
"events": "事件",
|
||||
"eventsHint": "选择此 webhook 应该接收更新的所有事件 (在当前项目内)。",
|
||||
"mustSelectEvents": "您必须选择至少一个事件。",
|
||||
"delete": "删除此 webhook?",
|
||||
"deleteText": "您确定要删除此Webhook吗?外部目标将不再收到其事件通知。",
|
||||
"deleteSuccess": "Webhook 已成功删除。",
|
||||
"create": "创建 Webhook",
|
||||
"secret": "密钥",
|
||||
"secretHint": "如果提供了 webhook 目标 URL 的所有请求都将使用 HMAC签名。",
|
||||
"secretDocs": "查看文档了解如何使用秘密的更多详情。"
|
||||
}
|
||||
},
|
||||
"filters": {
|
||||
|
@ -384,7 +385,7 @@
|
|||
"title": "标题",
|
||||
"titlePlaceholder": "填写筛选器标题",
|
||||
"description": "描述信息",
|
||||
"descriptionPlaceholder": "Add a description for this filter here, hit '/' for more options…",
|
||||
"descriptionPlaceholder": "在此处添加此过滤器的描述,点击'/'获取更多选项…",
|
||||
"includeNulls": "包含没有设置值的任务",
|
||||
"requireAll": "要求所有筛选器为真才能显示任务",
|
||||
"showDoneTasks": "显示已完成的任务",
|
||||
|
@ -398,9 +399,9 @@
|
|||
},
|
||||
"create": {
|
||||
"title": "新保存的过滤器",
|
||||
"description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed.",
|
||||
"description": "保存的过滤器是一个虚拟工程,每次访问时都从一组过滤器中计算。",
|
||||
"action": "创建新保存的过滤器",
|
||||
"titleRequired": "Please provide a title for the filter."
|
||||
"titleRequired": "请为该过滤器提供名称。"
|
||||
},
|
||||
"delete": {
|
||||
"header": "删除此保存的过滤器",
|
||||
|
@ -413,7 +414,7 @@
|
|||
}
|
||||
},
|
||||
"migrate": {
|
||||
"title": "Import from other services",
|
||||
"title": "从其他服务导入",
|
||||
"titleService": "从 {name} 导入您的数据到 Vikunja",
|
||||
"import": "导入数据到 Vikunja",
|
||||
"description": "点击下面的第三方服务的徽标开始操作。",
|
||||
|
@ -426,13 +427,13 @@
|
|||
"confirm": "我确定, 请立即开始迁移!",
|
||||
"importUpload": "请点击下面的按钮选择一个文件,将 {name} 的数据导入到 Vikunja",
|
||||
"upload": "点击上传文件",
|
||||
"migrationStartedWillReciveEmail": "Vikunja will now import your lists/projects, tasks, notes, reminders and files from {service}. As this will take a while, we will send you an email once done. You can close this window now.",
|
||||
"migrationInProgress": "A migration is currently in progress. Please wait until it is done."
|
||||
"migrationStartedWillReciveEmail": "Vikunja 现在将从 {service} 导入您的列表/项目、任务、注释、提醒和文件。 由于这需要一段时间,完成后我们会向您发送一封电子邮件。 您现在可以关闭此窗口。",
|
||||
"migrationInProgress": "迁移正在进行中。请等待完成。"
|
||||
},
|
||||
"label": {
|
||||
"title": "标签",
|
||||
"manage": "管理标签",
|
||||
"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 project you have access.",
|
||||
"description": "点击标签进行编辑。 您可以编辑您创建的所有标签,您可以使用所有与您有访问权限的任务相关联的标签。",
|
||||
"newCTA": "当前没有标签",
|
||||
"search": "输入以搜索标签…",
|
||||
"create": {
|
||||
|
@ -443,7 +444,7 @@
|
|||
},
|
||||
"edit": {
|
||||
"header": "编辑标签",
|
||||
"forbidden": "You are not allowed to edit this label because you don't own it.",
|
||||
"forbidden": "您无权编辑这个标签,因为您不拥有它。",
|
||||
"success": "标签已更新"
|
||||
},
|
||||
"deleteSuccess": "标签已删除",
|
||||
|
@ -457,7 +458,7 @@
|
|||
},
|
||||
"sharing": {
|
||||
"authenticating": "验证中……",
|
||||
"passwordRequired": "This shared project requires a password. Please enter it below:",
|
||||
"passwordRequired": "此共享项目需要密码。请在下面输入:",
|
||||
"error": "发生错误",
|
||||
"invalidPassword": "密码错误"
|
||||
},
|
||||
|
@ -498,7 +499,7 @@
|
|||
"custom": "自定义",
|
||||
"id": "ID",
|
||||
"created": "创建于",
|
||||
"createdBy": "Created by {0}",
|
||||
"createdBy": "由 {0} 创建",
|
||||
"actions": "行为",
|
||||
"cannotBeUndone": "此操作无法撤消!"
|
||||
},
|
||||
|
@ -517,59 +518,59 @@
|
|||
"edit": "编辑",
|
||||
"done": "完成",
|
||||
"heading1": "一级标题",
|
||||
"heading1Tooltip": "Big section heading.",
|
||||
"heading1Tooltip": "大标题。",
|
||||
"heading2": "二级标题",
|
||||
"heading2Tooltip": "Medium section heading.",
|
||||
"heading2Tooltip": "中标题。",
|
||||
"heading3": "三级标题",
|
||||
"heading3Tooltip": "Smaller section header.",
|
||||
"heading3Tooltip": "小标题。",
|
||||
"headingSmaller": "下一级标题",
|
||||
"headingBigger": "上一级标题",
|
||||
"bold": "粗体",
|
||||
"italic": "斜体",
|
||||
"strikethrough": "删除线",
|
||||
"underline": "Underline",
|
||||
"underline": "下划线",
|
||||
"code": "代码",
|
||||
"codeTooltip": "Capture a code snippet.",
|
||||
"codeTooltip": "捕获代码片段",
|
||||
"quote": "引用",
|
||||
"quoteTooltip": "Capture a quote.",
|
||||
"bulletList": "Bullet list",
|
||||
"bulletListTooltip": "Create a simple bullet list.",
|
||||
"unorderedList": "Unordered list",
|
||||
"orderedList": "Ordered list",
|
||||
"orderedListTooltip": "Create a list with numbering.",
|
||||
"quoteTooltip": "捕获引文。",
|
||||
"bulletList": "符号列表",
|
||||
"bulletListTooltip": "创建一个简单的符号列表。",
|
||||
"unorderedList": "无序列表",
|
||||
"orderedList": "有序列表",
|
||||
"orderedListTooltip": "创建带编号的列表。",
|
||||
"cleanBlock": "清除格式",
|
||||
"link": "链接",
|
||||
"image": "图片",
|
||||
"imageTooltip": "Upload an image from your computer.",
|
||||
"imageTooltip": "从您的计算机上传图片",
|
||||
"table": {
|
||||
"title": "Table",
|
||||
"insert": "Insert table",
|
||||
"addColumnBefore": "Add column before",
|
||||
"addColumnAfter": "Add column after",
|
||||
"deleteColumn": "Delete column",
|
||||
"addRowBefore": "Add row before",
|
||||
"addRowAfter": "Add row after",
|
||||
"deleteRow": "Delete row",
|
||||
"deleteTable": "Delete table",
|
||||
"mergeCells": "Merge cells",
|
||||
"splitCell": "Split cell",
|
||||
"toggleHeaderColumn": "Toggle header column",
|
||||
"toggleHeaderRow": "Toggle header row",
|
||||
"toggleHeaderCell": "Toggle header cell",
|
||||
"mergeOrSplit": "Merge or split",
|
||||
"fixTables": "Fix tables"
|
||||
"title": "表格",
|
||||
"insert": "插入表格",
|
||||
"addColumnBefore": "在前面添加列",
|
||||
"addColumnAfter": "在后面添加列",
|
||||
"deleteColumn": "删除整列",
|
||||
"addRowBefore": "在前面添加行",
|
||||
"addRowAfter": "在后面添加行",
|
||||
"deleteRow": "删除整行",
|
||||
"deleteTable": "删除表格",
|
||||
"mergeCells": "合并单元格",
|
||||
"splitCell": "拆分单元格",
|
||||
"toggleHeaderColumn": "切换头部列",
|
||||
"toggleHeaderRow": "切换头部行",
|
||||
"toggleHeaderCell": "切换头部单元格",
|
||||
"mergeOrSplit": "合并或拆分",
|
||||
"fixTables": "修复表格"
|
||||
},
|
||||
"horizontalRule": "水平线",
|
||||
"horizontalRuleTooltip": "Divide a section.",
|
||||
"horizontalRuleTooltip": "分割一节。",
|
||||
"sideBySide": "并排",
|
||||
"guide": "指南",
|
||||
"text": "Text",
|
||||
"textTooltip": "Just start typing with plain text.",
|
||||
"taskList": "Task list",
|
||||
"taskListTooltip": "Track tasks with a to-do list.",
|
||||
"undo": "Undo",
|
||||
"redo": "Redo",
|
||||
"placeholder": "Type some text or hit '/' to see more options…"
|
||||
"text": "文本",
|
||||
"textTooltip": "只需开始用纯文本键入。",
|
||||
"taskList": "任务列表",
|
||||
"taskListTooltip": "用待办事宜列表跟踪任务。",
|
||||
"undo": "撤销",
|
||||
"redo": "恢复",
|
||||
"placeholder": "输入一些文本或点击“/”查看更多选项…"
|
||||
},
|
||||
"multiselect": {
|
||||
"createPlaceholder": "创建新的",
|
||||
|
@ -599,14 +600,14 @@
|
|||
"canuse": "你可以使用 Date Math 来筛选相对日期。",
|
||||
"learnhow": "查看它如何工作",
|
||||
"title": "Date Math",
|
||||
"intro": "Specify relative dates which are resolved on the fly by Vikunja when applying the filter.",
|
||||
"intro": "指定应用过滤器时 Vikunja 即时解析的相对日期。",
|
||||
"expression": "每个 Date Math 表达式以锚点日期开头,可以是 {0},也可以是以 {1} 结尾的日期文本。 这个锚点日期后可以跟一个或多个数学表达式。",
|
||||
"similar": "这些表达式类似于 {0} 和 {1} 提供的表达式。",
|
||||
"add1Day": "加一天",
|
||||
"minus1Day": "减一天",
|
||||
"roundDay": "往最近的那天舍入",
|
||||
"supportedUnits": "Supported time units",
|
||||
"someExamples": "Examples of time expressions",
|
||||
"supportedUnits": "支持的时间单位是:",
|
||||
"someExamples": "时间表达式的一些例子:",
|
||||
"units": {
|
||||
"seconds": "秒数。",
|
||||
"minutes": "分钟",
|
||||
|
@ -635,7 +636,7 @@
|
|||
"addReminder": "添加一个新的提醒…",
|
||||
"doneSuccess": "待办事项已标记为完成。",
|
||||
"undoneSuccess": "待办事项已标记为未完成。",
|
||||
"undo": "Undo",
|
||||
"undo": "撤销",
|
||||
"openDetail": "查看任务详细信息",
|
||||
"checklistTotal": "{checked} 项任务,共 {total} 项。",
|
||||
"checklistAllDone": "一共 {total} 项任务",
|
||||
|
@ -652,7 +653,7 @@
|
|||
"chooseDueDate": "点击设定截止日期",
|
||||
"chooseStartDate": "点击设置开始日期",
|
||||
"chooseEndDate": "点击设定结束日期",
|
||||
"move": "Move task to a different project",
|
||||
"move": "将任务移动到另一个项目",
|
||||
"done": "标记为已完成",
|
||||
"undone": "标记为待办",
|
||||
"created": "{1} 创建于 {0}",
|
||||
|
@ -660,12 +661,12 @@
|
|||
"doneAt": "已完成 {0}",
|
||||
"updateSuccess": "该任务已保存",
|
||||
"deleteSuccess": "任务已删除",
|
||||
"belongsToProject": "This task belongs to project '{project}'",
|
||||
"belongsToProject": "该任务属于项目'{project}'",
|
||||
"due": "截止至 {at}",
|
||||
"closePopup": "关闭弹窗",
|
||||
"organization": "Organization",
|
||||
"management": "Management",
|
||||
"dateAndTime": "Date and time",
|
||||
"organization": "机构",
|
||||
"management": "管理",
|
||||
"dateAndTime": "日期与时间",
|
||||
"delete": {
|
||||
"header": "删除此任务",
|
||||
"text1": "确定要移除任务吗?",
|
||||
|
@ -683,7 +684,7 @@
|
|||
"percentDone": "设置进度",
|
||||
"attachments": "添加附件",
|
||||
"relatedTasks": "添加关联",
|
||||
"moveProject": "Move",
|
||||
"moveProject": "移动",
|
||||
"color": "设置颜色",
|
||||
"delete": "删除",
|
||||
"favorite": "添加至收藏",
|
||||
|
@ -710,15 +711,15 @@
|
|||
"updated": "已更新"
|
||||
},
|
||||
"subscription": {
|
||||
"subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.",
|
||||
"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.",
|
||||
"subscribedTaskThroughParentProject": "你无法在此处取消订阅,因为你已通过其项目订阅了此任务。",
|
||||
"subscribedProject": "你当前订阅了此项目,并将收到更改通知。",
|
||||
"notSubscribedProject": "你没有订阅此项目,也不会收到更改通知。",
|
||||
"subscribedTask": "你当前已订阅此任务并将收到更改通知。",
|
||||
"notSubscribedTask": "你没有订阅此任务,也不会收到更改通知。",
|
||||
"subscribe": "订阅",
|
||||
"unsubscribe": "取消订阅",
|
||||
"subscribeSuccessProject": "You are now subscribed to this project",
|
||||
"unsubscribeSuccessProject": "You are now unsubscribed to this project",
|
||||
"subscribeSuccessProject": "你现在订阅了此项目",
|
||||
"unsubscribeSuccessProject": "您已取消订阅此项目",
|
||||
"subscribeSuccessTask": "你现在订阅了此任务",
|
||||
"unsubscribeSuccessTask": "你现在已取消订阅此任务"
|
||||
},
|
||||
|
@ -743,7 +744,7 @@
|
|||
"loading": "正在加载评论…",
|
||||
"edited": "编辑于 {date}",
|
||||
"creating": "正在创建评论…",
|
||||
"placeholder": "Add your comment, hit '/' for more options…",
|
||||
"placeholder": "添加您的评论,点击“/”获取更多选项…",
|
||||
"comment": "评论",
|
||||
"delete": "删除此评论",
|
||||
"deleteText1": "确实要删除此评论吗?",
|
||||
|
@ -757,7 +758,7 @@
|
|||
"1week": "1周"
|
||||
},
|
||||
"description": {
|
||||
"placeholder": "Enter a description, hit '/' for more options…",
|
||||
"placeholder": "输入描述,点击'/'获取更多选项…",
|
||||
"empty": "尚无描述。"
|
||||
},
|
||||
"assignee": {
|
||||
|
@ -792,7 +793,7 @@
|
|||
"new": "新任务关系",
|
||||
"searchPlaceholder": "输入以搜索要添加关联的新任务...",
|
||||
"createPlaceholder": "添加为新的关联任务",
|
||||
"differentProject": "This task belongs to a different project.",
|
||||
"differentProject": "此任务属于另一个项目。",
|
||||
"noneYet": "还没有任务关联。",
|
||||
"delete": "删除关联",
|
||||
"deleteText1": "确定要删除此任务关联吗?",
|
||||
|
@ -813,20 +814,20 @@
|
|||
}
|
||||
},
|
||||
"reminder": {
|
||||
"before": "{amount} {unit} before {type}",
|
||||
"after": "{amount} {unit} after {type}",
|
||||
"beforeShort": "before",
|
||||
"afterShort": "after",
|
||||
"onDueDate": "On the due date",
|
||||
"onStartDate": "On the start date",
|
||||
"onEndDate": "On the end date",
|
||||
"custom": "Custom",
|
||||
"dateAndTime": "Date and time"
|
||||
"before": "{type}前{amount} {unit} ",
|
||||
"after": "{type}后{amount} {unit} ",
|
||||
"beforeShort": "之前",
|
||||
"afterShort": "之后",
|
||||
"onDueDate": "截止日期",
|
||||
"onStartDate": "开始日期",
|
||||
"onEndDate": "结束日期",
|
||||
"custom": "自定义",
|
||||
"dateAndTime": "日期与时间"
|
||||
},
|
||||
"repeat": {
|
||||
"everyDay": "每天",
|
||||
"everyWeek": "每周",
|
||||
"every30d": "Every 30 Days",
|
||||
"every30d": "每 30 天",
|
||||
"mode": "重复模式",
|
||||
"monthly": "每月",
|
||||
"fromCurrentDate": "从当前日期",
|
||||
|
@ -840,7 +841,7 @@
|
|||
"invalidAmount": "请输入大于 0 的数。"
|
||||
},
|
||||
"quickAddMagic": {
|
||||
"hint": "Use magic prefixes to define due dates, assignees and other task properties.",
|
||||
"hint": "使用魔法前缀来定义到期日期、受让人和其他任务属性。",
|
||||
"title": "快速添加 Magic",
|
||||
"intro": "创建任务时,可以使用特殊关键字直接为新创建的任务添加属性。 这能够更快地将常用属性添加到任务中。",
|
||||
"multiple": "你可以多次使用此功能。",
|
||||
|
@ -851,10 +852,10 @@
|
|||
"priority1": "要设置任务的优先级,请添加数字 1-5,并以 {prefix} 为前缀。",
|
||||
"priority2": "数字越大,优先级越高。",
|
||||
"assignees": "将任务分配给用户,请将带有 {prefix} 前缀的用户名添加到此任务中。",
|
||||
"project1": "To set a project for the task to appear in, enter its name prefixed with {prefix}.",
|
||||
"project2": "This will return an error if the project does not exist.",
|
||||
"project3": "To use spaces, simply add a \" or ' around the project name.",
|
||||
"project4": "For example: {prefix}\"Project with spaces\".",
|
||||
"project1": "要设置任务显示的项目,请输入其名称,前缀为{prefix}。",
|
||||
"project2": "如果项目不存在会返回错误。",
|
||||
"project3": "要使用空格,只需在项目名称周围添加一个 \" 或 '。",
|
||||
"project4": "例如:{prefix} “带空格的项目”。",
|
||||
"dateAndTime": "日期与时间",
|
||||
"date": "任何日期都将当做新任务的截止日期。 可以使用以下格式的日期:",
|
||||
"dateWeekday": "任意工作日,将使用该日期的下一个日期",
|
||||
|
@ -887,19 +888,19 @@
|
|||
"delete": {
|
||||
"header": "删除此团队",
|
||||
"text1": "确定要删除此团队及其所有成员吗?",
|
||||
"text2": "All team members will lose access to projects shared with this team. This CANNOT BE UNDONE!",
|
||||
"text2": "所有团队成员都将无法访问共享给该团队的项目。并且无法撤消!",
|
||||
"success": "团队已删除。"
|
||||
},
|
||||
"deleteUser": {
|
||||
"header": "从团队中删除用户",
|
||||
"text1": "确定要将此成员移出团队吗?",
|
||||
"text2": "They will lose access to all projects this team has access to. This CANNOT BE UNDONE!",
|
||||
"text2": "所有团队成员都将失去所有项目的访问权限,并且无法撤销!",
|
||||
"success": "此用户已成功从团队中删除。"
|
||||
},
|
||||
"leave": {
|
||||
"title": "离开团队",
|
||||
"text1": "您确定要离开这个团队吗?",
|
||||
"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.",
|
||||
"text2": "您将无法访问该团队拥有的所有项目。 如果你改变主意,你需要一个团队管理员来再次添加你。",
|
||||
"success": "您已经成功离开了团队。"
|
||||
}
|
||||
},
|
||||
|
@ -908,7 +909,7 @@
|
|||
"namePlaceholder": "团队的名字在这里……",
|
||||
"nameRequired": "请指定名称。",
|
||||
"description": "描述信息",
|
||||
"descriptionPlaceholder": "Describe the team here, hit '/' for more options…",
|
||||
"descriptionPlaceholder": "在此描述团队,点击'/'获取更多选项…",
|
||||
"admin": "管理员",
|
||||
"member": "成员"
|
||||
}
|
||||
|
@ -931,20 +932,20 @@
|
|||
"attachment": "向此任务添加附件。",
|
||||
"related": "修改此任务的相关任务",
|
||||
"color": "更改此任务的颜色",
|
||||
"move": "Move this task to another project",
|
||||
"move": "将此任务移至另一个项目。",
|
||||
"reminder": "管理此任务的提醒",
|
||||
"description": "切换编辑时的任务描述",
|
||||
"delete": "Delete this task",
|
||||
"priority": "Change the priority of this task",
|
||||
"favorite": "Mark this task as favorite / unfavorite",
|
||||
"save": "Save the current task"
|
||||
"delete": "删除此任务",
|
||||
"priority": "更改此任务的优先级",
|
||||
"favorite": "将此任务标记为收藏/取消收藏",
|
||||
"save": "保存当前任务"
|
||||
},
|
||||
"project": {
|
||||
"title": "Project Views",
|
||||
"switchToListView": "Switch to list view",
|
||||
"switchToGanttView": "Switch to gantt view",
|
||||
"switchToKanbanView": "Switch to kanban view",
|
||||
"switchToTableView": "Switch to table view"
|
||||
"title": "项目视图",
|
||||
"switchToListView": "切换到列表视图",
|
||||
"switchToGanttView": "切换到甘特图",
|
||||
"switchToKanbanView": "切换到看板视图",
|
||||
"switchToTableView": "切换为表格视图"
|
||||
},
|
||||
"navigation": {
|
||||
"title": "导航栏",
|
||||
|
@ -952,11 +953,11 @@
|
|||
"upcoming": "导航到即将到来的任务",
|
||||
"labels": "导航到标签",
|
||||
"teams": "导航到小组",
|
||||
"projects": "Navigate to projects"
|
||||
"projects": "导航到项目"
|
||||
}
|
||||
},
|
||||
"update": {
|
||||
"available": "There is an update available!",
|
||||
"available": "有新版本可用。",
|
||||
"do": "立即更新"
|
||||
},
|
||||
"menu": {
|
||||
|
@ -967,15 +968,15 @@
|
|||
"unarchive": "取消存档",
|
||||
"setBackground": "设置背景",
|
||||
"share": "共享",
|
||||
"newProject": "New project",
|
||||
"createProject": "Create project"
|
||||
"newProject": "新项目",
|
||||
"createProject": "创建项目"
|
||||
},
|
||||
"apiConfig": {
|
||||
"url": "Vikunja URL",
|
||||
"urlPlaceholder": "例如: http://localhost:3456",
|
||||
"change": "换一换",
|
||||
"use": "在 {0} 使用 Vikunja 安装程序",
|
||||
"error": "Could not find or use Vikunja installation at \"{domain}\". Please check if the url has the correct format and you can reach it when accessing it directly and try again.",
|
||||
"error": "无法在“{domain}”找到或使用 Vikunja 安装。 请检查url格式是否正确,直接访问是否可以访问,然后重试。",
|
||||
"success": "在 “{domain}” 上使用 Vikunja 安装程序。",
|
||||
"urlRequired": "Url 是必需的。"
|
||||
},
|
||||
|
@ -987,26 +988,26 @@
|
|||
"notification": {
|
||||
"title": "通知",
|
||||
"none": "没有任何通知。 祝你今天过得愉快!",
|
||||
"explainer": "Notifications will appear here when actions projects or tasks you subscribed to happen.",
|
||||
"markAllRead": "Mark all notifications as read",
|
||||
"markAllReadSuccess": "Successfully marked all notifications as read."
|
||||
"explainer": "当您订阅项目或任务发生时,通知将会显示在这里。",
|
||||
"markAllRead": "将所有通知标为已读",
|
||||
"markAllReadSuccess": "成功标记所有通知为已读。"
|
||||
},
|
||||
"quickActions": {
|
||||
"commands": "命令",
|
||||
"placeholder": "输入命令或搜索…",
|
||||
"hint": "You can use {project} to limit the search to a project. Combine {project} or {label} (labels) with a search query to search for a task with these labels or on that project. Use {assignee} to only search for teams.",
|
||||
"hint": "可以使用 {project} 将搜索限制在项目中。 将 {project} 或 {label}(标签)与搜索查询相结合,可以搜索有这些标签或在该项目中的任务。 {assignee} 仅适用于在团队中搜索。",
|
||||
"tasks": "任务",
|
||||
"projects": "Projects",
|
||||
"projects": "项目",
|
||||
"teams": "团队",
|
||||
"labels": "Labels",
|
||||
"newProject": "Enter the title of the new project…",
|
||||
"labels": "标签",
|
||||
"newProject": "输入新项目的标题…",
|
||||
"newTask": "输入新任务的标题...",
|
||||
"newTeam": "输入新团队的名称...",
|
||||
"createTask": "Create a task in the current project ({title})",
|
||||
"createProject": "Create a project",
|
||||
"createTask": "在当前项目中创建一个任务 ({title})",
|
||||
"createProject": "创建一个项目",
|
||||
"cmds": {
|
||||
"newTask": "新建任务",
|
||||
"newProject": "New project",
|
||||
"newProject": "新项目",
|
||||
"newTeam": "新建团队"
|
||||
}
|
||||
},
|
||||
|
@ -1037,15 +1038,15 @@
|
|||
"1018": "用户头像设置无效。",
|
||||
"2001": "ID 不能为空或 0。",
|
||||
"2002": "一些请求数据无效。",
|
||||
"3001": "The project does not exist.",
|
||||
"3004": "You need to have read permissions on that project to perform that action.",
|
||||
"3005": "The project title cannot be empty.",
|
||||
"3006": "The project share does not exist.",
|
||||
"3007": "A project with this identifier already exists.",
|
||||
"3008": "The project is archived and can therefore only be accessed read only. This is also true for all tasks associated with this project.",
|
||||
"4001": "The project task text cannot be empty.",
|
||||
"4002": "The project task does not exist.",
|
||||
"4003": "All bulk editing tasks must belong to the same project.",
|
||||
"3001": "项目不存在",
|
||||
"3004": "您需要读取该项目的权限才能执行此操作。",
|
||||
"3005": "列表标题不能为空。",
|
||||
"3006": "项目共享不存在。",
|
||||
"3007": "具有此标识符的项目已存在。",
|
||||
"3008": "该项目已存档,因此只能读取。与该项目相关的所有任务也是如此。",
|
||||
"4001": "项目任务文本不能为空。",
|
||||
"4002": "项目任务不存在。",
|
||||
"4003": "所有批量编辑任务必须属于同一项目。",
|
||||
"4004": "批量编辑任务时至少需要选择一项任务。",
|
||||
"4005": "你没有权限查看此任务。",
|
||||
"4006": "不能将上级任务设置为任务本身。",
|
||||
|
@ -1064,21 +1065,21 @@
|
|||
"4019": "任务筛选值无效。",
|
||||
"6001": "团队名称不能为空。",
|
||||
"6002": "团队不存在。",
|
||||
"6004": "The team already has access to that project.",
|
||||
"6004": "该团队已经可以访问该项目。",
|
||||
"6005": "该用户已经是此团队的成员。",
|
||||
"6006": "无法删除最后一个团队成员。",
|
||||
"6007": "The team does not have access to the project to perform that action.",
|
||||
"7002": "The user already has access to that project.",
|
||||
"7003": "You do not have access to that project.",
|
||||
"6007": "该团队没有权限访问此项目来执行操作。",
|
||||
"7002": "用户已经有权访问此项目。",
|
||||
"7003": "您无权访问此项目",
|
||||
"8001": "此标签已存在于该任务中。",
|
||||
"8002": "标签不存在。",
|
||||
"8003": "你没有权限访问此标签。",
|
||||
"9001": "权限无效。",
|
||||
"10001": "存储桶不存在。",
|
||||
"10002": "The bucket does not belong to that project.",
|
||||
"10003": "You cannot remove the last bucket on a project.",
|
||||
"10002": "此存储桶不属于该项目。",
|
||||
"10003": "无法删除项目中的最后一个存储桶。",
|
||||
"10004": "无法将任务添加到此存储桶,因为已超过此存储桶可容纳的任务限制。",
|
||||
"10005": "There can be only one done bucket per project.",
|
||||
"10005": "每个项目只能有一个已完成的桶。",
|
||||
"11001": "已保存筛选器不存在。",
|
||||
"11002": "已保存的筛选器不适用于链接共享。",
|
||||
"12001": "订阅实体类型无效。",
|
||||
|
@ -1093,13 +1094,13 @@
|
|||
},
|
||||
"time": {
|
||||
"units": {
|
||||
"seconds": "second|seconds",
|
||||
"minutes": "minute|minutes",
|
||||
"hours": "hour|hours",
|
||||
"days": "day|days",
|
||||
"weeks": "week|weeks",
|
||||
"months": "month|months",
|
||||
"years": "year|years"
|
||||
"seconds": "秒|秒",
|
||||
"minutes": "分|分钟",
|
||||
"hours": "时|小时",
|
||||
"days": "天|天",
|
||||
"weeks": "周|周",
|
||||
"months": "月|月",
|
||||
"years": "年|年"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -160,6 +160,7 @@
|
|||
"expired": "This token has expired {ago}.",
|
||||
"tokenCreatedSuccess": "Here is your new api token: {token}",
|
||||
"tokenCreatedNotSeeAgain": "Store it in a secure location, you won't see it again!",
|
||||
"selectAll": "Select all",
|
||||
"delete": {
|
||||
"header": "Delete this token",
|
||||
"text1": "Are you sure you want to delete the token \"{token}\"?",
|
||||
|
|
|
@ -112,6 +112,16 @@ describe('Parse Task Text', () => {
|
|||
expect(result?.date?.getMonth()).toBe(tomorrow.getMonth())
|
||||
expect(result?.date?.getDate()).toBe(tomorrow.getDate())
|
||||
})
|
||||
it('should recognize Tomorrow', () => {
|
||||
const result = parseTaskText('Lorem Ipsum Tomorrow')
|
||||
|
||||
expect(result.text).toBe('Lorem Ipsum')
|
||||
const tomorrow = new Date()
|
||||
tomorrow.setDate(tomorrow.getDate() + 1)
|
||||
expect(result?.date?.getFullYear()).toBe(tomorrow.getFullYear())
|
||||
expect(result?.date?.getMonth()).toBe(tomorrow.getMonth())
|
||||
expect(result?.date?.getDate()).toBe(tomorrow.getDate())
|
||||
})
|
||||
it('should recognize next monday', () => {
|
||||
const result = parseTaskText('Lorem Ipsum next monday')
|
||||
|
||||
|
@ -441,7 +451,7 @@ describe('Parse Task Text', () => {
|
|||
'06/08/2021': '2021-6-8',
|
||||
'6/7/21': '2021-6-7',
|
||||
'27/07/2021,': null,
|
||||
'2021/07/06,': '2021-7-6',
|
||||
'2021/07/06': '2021-7-6',
|
||||
'2021-07-06': '2021-7-6',
|
||||
'27 jan': '2022-1-27',
|
||||
'27/1': '2022-1-27',
|
||||
|
@ -449,39 +459,52 @@ describe('Parse Task Text', () => {
|
|||
'16/12': '2021-12-16',
|
||||
'01/27': '2022-1-27',
|
||||
'1/27': '2022-1-27',
|
||||
'Jan 27': '2022-1-27',
|
||||
'jan 27': '2022-1-27',
|
||||
'Jan 27': '2022-1-27',
|
||||
'feb 21': '2022-2-21',
|
||||
'Feb 21': '2022-2-21',
|
||||
'mar 21': '2022-3-21',
|
||||
'Mar 21': '2022-3-21',
|
||||
'apr 21': '2022-4-21',
|
||||
'Apr 21': '2022-4-21',
|
||||
'may 21': '2022-5-21',
|
||||
'May 21': '2022-5-21',
|
||||
'jun 21': '2022-6-21',
|
||||
'Jun 21': '2022-6-21',
|
||||
'jul 21': '2021-7-21',
|
||||
'Jul 21': '2021-7-21',
|
||||
'aug 21': '2021-8-21',
|
||||
'Aug 21': '2021-8-21',
|
||||
'sep 21': '2021-9-21',
|
||||
'Sep 21': '2021-9-21',
|
||||
'oct 21': '2021-10-21',
|
||||
'Oct 21': '2021-10-21',
|
||||
'nov 21': '2021-11-21',
|
||||
'Nov 21': '2021-11-21',
|
||||
'dec 21': '2021-12-21',
|
||||
'Dec 21': '2021-12-21',
|
||||
} as Record<string, string | null>
|
||||
|
||||
for (const c in cases) {
|
||||
it(`should parse '${c}' as '${cases[c]}' with the date at the end`, () => {
|
||||
const {date} = getDateFromText(`Lorem Ipsum ${c}`, now)
|
||||
const {date, foundText} = getDateFromText(`Lorem Ipsum ${c}`, now)
|
||||
if (date === null && cases[c] === null) {
|
||||
expect(date).toBeNull()
|
||||
return
|
||||
}
|
||||
|
||||
expect(`${date?.getFullYear()}-${date?.getMonth() + 1}-${date?.getDate()}`).toBe(cases[c])
|
||||
expect(foundText.trim()).toBe(c)
|
||||
})
|
||||
it(`should parse '${c}' as '${cases[c]}' with the date at the beginning`, () => {
|
||||
const {date} = getDateFromText(`${c} Lorem Ipsum`, now)
|
||||
const {date, foundText} = getDateFromText(`${c} Lorem Ipsum`, now)
|
||||
if (date === null && cases[c] === null) {
|
||||
expect(date).toBeNull()
|
||||
return
|
||||
}
|
||||
|
||||
expect(`${date?.getFullYear()}-${date?.getMonth() + 1}-${date?.getDate()}`).toBe(cases[c])
|
||||
expect(foundText.trim()).toBe(c)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
@ -532,6 +555,20 @@ describe('Parse Task Text', () => {
|
|||
expect(`${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()} ${date.getHours()}:${date.getMinutes()}`).toBe(cases[c])
|
||||
})
|
||||
}
|
||||
|
||||
it('should replace the text in title case', () => {
|
||||
const {date, newText} = parseDate('Some task Mar 8th', now)
|
||||
|
||||
expect(`${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()} ${date.getHours()}:${date.getMinutes()}`).toBe('2021-3-8 12:0')
|
||||
expect(newText).toBe('Some task')
|
||||
})
|
||||
|
||||
it('should replace the text in lowercase', () => {
|
||||
const {date, newText} = parseDate('Some task mar 8th', now)
|
||||
|
||||
expect(`${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()} ${date.getHours()}:${date.getMinutes()}`).toBe('2021-3-8 12:0')
|
||||
expect(newText).toBe('Some task')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ import {useI18n} from 'vue-i18n'
|
|||
import type {RouteLocationNormalized} from 'vue-router'
|
||||
|
||||
import {useBaseStore} from '@/stores/base'
|
||||
import {useAuthStore} from '@/stores/auth'
|
||||
import { getFlatpickrLanguage } from '@/helpers/flatpickrLanguage'
|
||||
|
||||
import Foo from '@/components/misc/flatpickr/Flatpickr.vue'
|
||||
import ProjectWrapper from '@/components/project/ProjectWrapper.vue'
|
||||
|
@ -126,16 +126,13 @@ const flatPickerDateRange = computed<Date[]>({
|
|||
const initialDateRange = [filters.value.dateFrom, filters.value.dateTo]
|
||||
|
||||
const {t} = useI18n({useScope: 'global'})
|
||||
const authStore = useAuthStore()
|
||||
const flatPickerConfig = computed<Options>(() => ({
|
||||
altFormat: t('date.altFormatShort'),
|
||||
altInput: true,
|
||||
defaultDate: initialDateRange,
|
||||
enableTime: false,
|
||||
mode: 'range',
|
||||
locale: {
|
||||
firstDayOfWeek: authStore.settings.weekStart,
|
||||
},
|
||||
locale: getFlatpickrLanguage(),
|
||||
}))
|
||||
</script>
|
||||
|
||||
|
|
|
@ -10,9 +10,9 @@ import {MILLISECONDS_A_DAY} from '@/constants/date'
|
|||
import flatPickr from 'vue-flatpickr-component'
|
||||
import 'flatpickr/dist/flatpickr.css'
|
||||
import {useI18n} from 'vue-i18n'
|
||||
import {useAuthStore} from '@/stores/auth'
|
||||
import Message from '@/components/misc/message.vue'
|
||||
import type {IApiToken} from '@/modelTypes/IApiToken'
|
||||
import { getFlatpickrLanguage } from '@/helpers/flatpickrLanguage'
|
||||
|
||||
const service = new ApiTokenService()
|
||||
const tokens = ref<IApiToken[]>([])
|
||||
|
@ -32,18 +32,16 @@ const showDeleteModal = ref<boolean>(false)
|
|||
const tokenToDelete = ref<IApiToken>()
|
||||
|
||||
const {t} = useI18n()
|
||||
const authStore = useAuthStore()
|
||||
|
||||
const now = new Date()
|
||||
|
||||
const flatPickerConfig = computed(() => ({
|
||||
altFormat: t('date.altFormatLong'),
|
||||
altInput: true,
|
||||
dateFormat: 'Y-m-d H:i',
|
||||
enableTime: true,
|
||||
time_24hr: true,
|
||||
locale: {
|
||||
firstDayOfWeek: authStore.settings.weekStart,
|
||||
},
|
||||
locale: getFlatpickrLanguage(),
|
||||
minDate: now,
|
||||
}))
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user