feat: bulk-operations (#2346)

Co-authored-by: PatrikKozak <patrik@trbl.design>
This commit is contained in:
Dan Ribbens
2023-03-23 12:33:13 -04:00
committed by GitHub
parent c5cb08c5b8
commit 0fedbabe9e
112 changed files with 4833 additions and 1385 deletions

View File

@@ -189,12 +189,10 @@ const Routes = () => {
render={(routeProps) => {
if (permissions?.collections?.[collection.slug]?.read?.permission) {
return (
<TableColumnsProvider collection={collection}>
<List
{...routeProps}
collection={collection}
/>
</TableColumnsProvider>
<List
{...routeProps}
collection={collection}
/>
);
}

View File

@@ -1,4 +1,4 @@
import React, { useId } from 'react';
import React, { useId, useState } from 'react';
import { useTranslation } from 'react-i18next';
import Pill from '../Pill';
import Plus from '../../icons/Plus';
@@ -49,6 +49,8 @@ const ColumnSelector: React.FC<Props> = (props) => {
name,
} = col;
if (col.accessor === '_select') return null;
return (
<Pill
draggable

View File

@@ -0,0 +1,17 @@
@import '../../../scss/styles.scss';
.delete-documents {
@include blur-bg;
display: flex;
align-items: center;
height: 100%;
&__template {
z-index: 1;
position: relative;
}
.btn {
margin-right: $baseline;
}
}

View File

@@ -0,0 +1,120 @@
import React, { useState, useCallback } from 'react';
import { toast } from 'react-toastify';
import { Modal, useModal } from '@faceless-ui/modal';
import { useTranslation } from 'react-i18next';
import { useConfig } from '../../utilities/Config';
import Button from '../Button';
import MinimalTemplate from '../../templates/Minimal';
import { requests } from '../../../api';
import { Props } from './types';
import { SelectAllStatus, useSelection } from '../../views/collections/List/SelectionProvider';
import { getTranslation } from '../../../../utilities/getTranslation';
import Pill from '../Pill';
import { useAuth } from '../../utilities/Auth';
import './index.scss';
const baseClass = 'delete-documents';
const DeleteMany: React.FC<Props> = (props) => {
const {
resetParams,
collection: {
slug,
labels: {
plural,
},
} = {},
} = props;
const { permissions } = useAuth();
const { serverURL, routes: { api } } = useConfig();
const { toggleModal } = useModal();
const { selectAll, count, getQueryParams, toggleAll } = useSelection();
const { t, i18n } = useTranslation('general');
const [deleting, setDeleting] = useState(false);
const collectionPermissions = permissions?.collections?.[slug];
const hasDeletePermission = collectionPermissions?.delete?.permission;
const modalSlug = `delete-${slug}`;
const addDefaultError = useCallback(() => {
toast.error(t('error:unknown'));
}, [t]);
const handleDelete = useCallback(() => {
setDeleting(true);
requests.delete(`${serverURL}${api}/${slug}${getQueryParams()}`, {
headers: {
'Content-Type': 'application/json',
'Accept-Language': i18n.language,
},
}).then(async (res) => {
try {
const json = await res.json();
toggleModal(modalSlug);
if (res.status < 400) {
toast.success(json.message || t('deletedSuccessfully'), { autoClose: 3000 });
toggleAll();
resetParams({ page: selectAll ? 1 : undefined });
return null;
}
if (json.errors) {
toast.error(json.message);
} else {
addDefaultError();
}
return false;
} catch (e) {
return addDefaultError();
}
});
}, [addDefaultError, api, getQueryParams, i18n.language, modalSlug, resetParams, selectAll, serverURL, slug, t, toggleAll, toggleModal]);
if (selectAll === SelectAllStatus.None || !hasDeletePermission) {
return null;
}
return (
<React.Fragment>
<Pill
className={`${baseClass}__toggle`}
onClick={() => {
setDeleting(false);
toggleModal(modalSlug);
}}
>
{t('delete')}
</Pill>
<Modal
slug={modalSlug}
className={baseClass}
>
<MinimalTemplate className={`${baseClass}__template`}>
<h1>{t('confirmDeletion')}</h1>
<p>
{t('aboutToDeleteCount', { label: getTranslation(plural, i18n), count })}
</p>
<Button
id="confirm-cancel"
buttonStyle="secondary"
type="button"
onClick={deleting ? undefined : () => toggleModal(modalSlug)}
>
{t('cancel')}
</Button>
<Button
onClick={deleting ? undefined : handleDelete}
id="confirm-delete"
>
{deleting ? t('deleting') : t('confirm')}
</Button>
</MinimalTemplate>
</Modal>
</React.Fragment>
);
};
export default DeleteMany;

View File

@@ -0,0 +1,8 @@
import { SanitizedCollectionConfig } from '../../../../collections/config/types';
import type { Props as ListProps } from '../../views/collections/List/types';
export type Props = {
collection: SanitizedCollectionConfig,
title?: string,
resetParams: ListProps['resetParams'],
}

View File

@@ -0,0 +1,190 @@
@import '../../../scss/styles.scss';
.edit-many {
&__toggle {
font-size: 1rem;
line-height: base(1);
display: inline-flex;
background: var(--theme-elevation-150);
color: var(--theme-elevation-800);
border-radius: $style-radius-s;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
border: 0;
padding: 0 base(.25);
align-items: center;
cursor: pointer;
text-decoration: none;
&:active,
&:focus {
outline: none;
}
&:hover {
background: var(--theme-elevation-100);
}
&:active {
background: var(--theme-elevation-100);
}
}
&__form {
height: 100%;
}
&__main {
width: calc(100% - #{base(15)});
display: flex;
flex-direction: column;
min-height: 100%;
}
&__header {
display: flex;
margin-top: base(2.5);
margin-bottom: base(1);
width: 100%;
&__title {
margin: 0;
flex-grow: 1;
}
&__close {
border: 0;
background-color: transparent;
padding: 0;
cursor: pointer;
overflow: hidden;
width: base(1);
height: base(1);
svg {
width: base(2.75);
height: base(2.75);
position: relative;
left: base(-.825);
top: base(-.825);
.stroke {
stroke-width: 2px;
vector-effect: non-scaling-stroke;
}
}
}
}
&__edit {
padding-top: base(1);
padding-bottom: base(2);
flex-grow: 1;
}
&__sidebar-wrap {
position: fixed;
width: base(15);
height: 100%;
top: 0;
right: 0;
overflow: visible;
border-left: 1px solid var(--theme-elevation-100);
}
&__sidebar {
width: 100%;
height: 100%;
overflow-y: auto;
}
&__sidebar-sticky-wrap {
display: flex;
flex-direction: column;
min-height: 100%;
}
&__collection-actions,
&__meta,
&__sidebar-fields {
padding-left: base(1.5);
}
&__document-actions {
padding-right: $baseline;
position: sticky;
top: 0;
z-index: var(--z-nav);
> * {
position: relative;
z-index: 1;
}
@include mid-break {
@include blur-bg;
}
}
&__document-actions {
display: flex;
flex-wrap: wrap;
padding: base(1);
gap: base(.5);
.form-submit {
width: calc(50% - #{base(1)});
@include mid-break {
width: auto;
flex-grow: 1;
}
.btn {
width: 100%;
padding-left: base(.5);
padding-right: base(.5);
margin-bottom: 0;
}
}
}
@include mid-break {
&__main {
width: 100%;
min-height: initial;
}
&__sidebar-wrap {
position: static;
width: 100%;
height: initial;
}
&__form {
display: block;
}
&__edit {
padding-top: 0;
padding-bottom: 0;
}
&__document-actions {
position: fixed;
bottom: 0;
left: 0;
right: 0;
top: auto;
z-index: var(--z-nav);
}
&__document-actions,
&__sidebar-fields {
padding-left: var(--gutter-h);
padding-right: var(--gutter-h);
}
}
}

View File

@@ -0,0 +1,204 @@
import React, { useCallback, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useModal } from '@faceless-ui/modal';
import { useConfig } from '../../utilities/Config';
import { Drawer, DrawerToggler } from '../Drawer';
import { Props } from './types';
import { SelectAllStatus, useSelection } from '../../views/collections/List/SelectionProvider';
import { getTranslation } from '../../../../utilities/getTranslation';
import { useAuth } from '../../utilities/Auth';
import { FieldSelect } from '../FieldSelect';
import FormSubmit from '../../forms/Submit';
import Form from '../../forms/Form';
import { useForm } from '../../forms/Form/context';
import RenderFields from '../../forms/RenderFields';
import { OperationContext } from '../../utilities/OperationProvider';
import fieldTypes from '../../forms/field-types';
import X from '../../icons/X';
import './index.scss';
const baseClass = 'edit-many';
const Submit: React.FC<{disabled: boolean, action: string}> = ({ action, disabled }) => {
const { submit } = useForm();
const { t } = useTranslation('general');
const save = useCallback(() => {
submit({
skipValidation: true,
method: 'PATCH',
action,
});
}, [action, submit]);
return (
<FormSubmit
className={`${baseClass}__save`}
onClick={save}
disabled={disabled}
>
{t('save')}
</FormSubmit>
);
};
const Publish: React.FC<{disabled: boolean, action: string}> = ({ action, disabled }) => {
const { submit } = useForm();
const { t } = useTranslation('version');
const save = useCallback(() => {
submit({
skipValidation: true,
method: 'PATCH',
overrides: {
_status: 'published',
},
action,
});
}, [action, submit]);
return (
<FormSubmit
className={`${baseClass}__publish`}
onClick={save}
disabled={disabled}
>
{t('publishChanges')}
</FormSubmit>
);
};
const SaveDraft: React.FC<{disabled: boolean, action: string}> = ({ action, disabled }) => {
const { submit } = useForm();
const { t } = useTranslation('version');
const save = useCallback(() => {
submit({
skipValidation: true,
method: 'PATCH',
overrides: {
_status: 'draft',
},
action,
});
}, [action, submit]);
return (
<FormSubmit
className={`${baseClass}__draft`}
onClick={save}
disabled={disabled}
>
{t('saveDraft')}
</FormSubmit>
);
};
const EditMany: React.FC<Props> = (props) => {
const {
resetParams,
collection,
collection: {
slug,
labels: {
plural,
},
fields,
} = {},
} = props;
const { permissions } = useAuth();
const { closeModal } = useModal();
const { serverURL, routes: { api } } = useConfig();
const { selectAll, count, getQueryParams } = useSelection();
const { t, i18n } = useTranslation('general');
const [selected, setSelected] = useState([]);
const collectionPermissions = permissions?.collections?.[slug];
const hasUpdatePermission = collectionPermissions?.update?.permission;
const drawerSlug = `edit-${slug}`;
if (selectAll === SelectAllStatus.None || !hasUpdatePermission) {
return null;
}
const onSuccess = () => {
resetParams({ page: selectAll === SelectAllStatus.AllAvailable ? 1 : undefined });
};
return (
<div className={baseClass}>
<DrawerToggler
slug={drawerSlug}
className={`${baseClass}__toggle`}
aria-label={t('edit')}
onClick={() => {
setSelected([]);
}}
>
{t('edit')}
</DrawerToggler>
<Drawer
slug={drawerSlug}
header={null}
>
<OperationContext.Provider value="update">
<Form
className={`${baseClass}__form`}
onSuccess={onSuccess}
>
<div className={`${baseClass}__main`}>
<div className={`${baseClass}__header`}>
<h2 className={`${baseClass}__header__title`}>
{t('editingLabel', { label: getTranslation(plural, i18n), count })}
</h2>
<button
className={`${baseClass}__header__close`}
id={`close-drawer__${drawerSlug}`}
type="button"
onClick={() => closeModal(drawerSlug)}
aria-label={t('close')}
>
<X />
</button>
</div>
<FieldSelect
fields={fields}
setSelected={setSelected}
/>
<RenderFields
fieldTypes={fieldTypes}
fieldSchema={selected}
/>
<div className={`${baseClass}__sidebar-wrap`}>
<div className={`${baseClass}__sidebar`}>
<div className={`${baseClass}__sidebar-sticky-wrap`}>
<div className={`${baseClass}__document-actions`}>
<Submit
action={`${serverURL}${api}/${slug}${getQueryParams()}`}
disabled={selected.length === 0}
/>
{ collection.versions && (
<React.Fragment>
<Publish
action={`${serverURL}${api}/${slug}${getQueryParams()}`}
disabled={selected.length === 0}
/>
<SaveDraft
action={`${serverURL}${api}/${slug}${getQueryParams()}`}
disabled={selected.length === 0}
/>
</React.Fragment>
)}
</div>
</div>
</div>
</div>
</div>
</Form>
</OperationContext.Provider>
</Drawer>
</div>
);
};
export default EditMany;

View File

@@ -0,0 +1,7 @@
import { SanitizedCollectionConfig } from '../../../../collections/config/types';
import type { Props as ListProps } from '../../views/collections/List/types';
export type Props = {
collection: SanitizedCollectionConfig,
resetParams: ListProps['resetParams'],
}

View File

@@ -0,0 +1,5 @@
@import '../../../scss/styles.scss';
.field-select {
margin-bottom: base(1);
}

View File

@@ -0,0 +1,101 @@
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import {
Field, fieldAffectsData,
fieldHasSubFields, FieldWithPath,
tabHasName,
} from '../../../../fields/config/types';
import ReactSelect from '../ReactSelect';
import { getTranslation } from '../../../../utilities/getTranslation';
import Label from '../../forms/Label';
import { useForm } from '../../forms/Form/context';
import { createNestedFieldPath } from '../../forms/Form/createNestedFieldPath';
import './index.scss';
const baseClass = 'field-select';
type Props = {
fields: Field[];
setSelected: (fields: FieldWithPath[]) => void
}
const combineLabel = (prefix, field, i18n): string => (
`${prefix === '' ? '' : `${prefix} > `}${getTranslation(field.label || field.name, i18n) || ''}`
);
const reduceFields = (fields: Field[], i18n, path = '', labelPrefix = ''): {label: string, value: FieldWithPath}[] => (
fields.reduce((fieldsToUse, field) => {
// escape for a variety of reasons
if (fieldAffectsData(field) && (field.admin?.disableBulkEdit || field.unique || field.hidden || field.admin?.hidden || field.admin?.readOnly)) {
return fieldsToUse;
}
if (!(field.type === 'array' || field.type === 'blocks') && fieldHasSubFields(field)) {
return [
...fieldsToUse,
...reduceFields(field.fields, i18n, createNestedFieldPath(path, field), combineLabel(labelPrefix, field, i18n)),
];
}
if (field.type === 'tabs') {
return [
...fieldsToUse,
...field.tabs.reduce((tabFields, tab) => {
return [
...tabFields,
...(reduceFields(tab.fields, i18n, tabHasName(tab) ? createNestedFieldPath(path, field) : path, combineLabel(labelPrefix, field, i18n))),
];
}, []),
];
}
const formattedField = {
label: combineLabel(labelPrefix, field, i18n),
value: {
...field,
path: createNestedFieldPath(path, field),
},
};
return [
...fieldsToUse,
formattedField,
];
}, []));
export const FieldSelect: React.FC<Props> = ({
fields,
setSelected,
}) => {
const { t, i18n } = useTranslation('general');
const [options] = useState(() => reduceFields(fields, i18n));
const { getFields, dispatchFields } = useForm();
const handleChange = (selected) => {
const activeFields = getFields();
if (selected === null) {
setSelected([]);
} else {
setSelected(selected.map(({ value }) => value));
}
// remove deselected values from form state
if (selected === null || Object.keys(activeFields).length > selected.length) {
Object.keys(activeFields).forEach((path) => {
if (selected === null || !selected.find((field) => {
return field.value.path === path;
})) {
dispatchFields({
type: 'REMOVE',
path,
});
}
});
}
};
return (
<div className={baseClass}>
<Label label={t('fields:selectFieldsToEdit')} />
<ReactSelect
options={options}
isMulti
onChange={handleChange}
/>
</div>
);
};

View File

@@ -5,6 +5,8 @@
&__wrap {
display: flex;
align-items: center;
background-color: var(--theme-elevation-50);
}
.search-filter {
@@ -21,24 +23,28 @@
&__buttons-wrap {
display: flex;
margin-left: - base(.5);
margin-right: - base(.5);
width: calc(100% + #{base(1)});
align-items: center;
margin-right: base(.5);
.btn, .pill {
margin: 0 0 0 base(.5);
}
.btn {
margin: 0 base(.5);
background-color: var(--theme-elevation-100);
cursor: pointer;
padding: 0 base(.25);
border-radius: $style-radius-s;
&:hover {
background-color: var(--theme-elevation-200);
}
}
}
&__toggle-columns,
&__toggle-where,
&__toggle-sort {
min-width: 140px;
&.btn--style-primary {
svg {
transform: rotate(180deg);
}
&__buttons-active {
svg {
transform: rotate(180deg);
}
}
@@ -48,25 +54,10 @@
margin-top: base(1);
}
@include mid-break {
&__buttons {
margin-left: base(.5);
}
&__buttons-wrap {
margin-left: - base(.25);
margin-right: - base(.25);
width: calc(100% + #{base(0.5)});
.btn {
margin: 0 base(.25);
}
}
}
@include small-break {
&__wrap {
flex-wrap: wrap;
background-color: unset;
}
.search-filter {
@@ -74,11 +65,23 @@
width: 100%;
}
&__buttons {
margin: 0;
&__buttons-wrap {
margin-left: - base(.25);
margin-right: - base(.25);
width: calc(100% + #{base(0.5)});
.pill {
margin: 0 base(.25);
padding: base(.5) base(1);
svg {
margin-left: auto;
}
}
}
&__buttons {
margin: 0;
width: 100%;
}

View File

@@ -1,6 +1,7 @@
import React, { useState } from 'react';
import AnimateHeight from 'react-animate-height';
import { useTranslation } from 'react-i18next';
import { useWindowInfo } from '@faceless-ui/window-info';
import { fieldAffectsData } from '../../../../fields/config/types';
import SearchFilter from '../SearchFilter';
import ColumnSelector from '../ColumnSelector';
@@ -13,6 +14,12 @@ import validateWhereQuery from '../WhereBuilder/validateWhereQuery';
import flattenFields from '../../../../utilities/flattenTopLevelFields';
import { getTextFieldsToBeSearched } from './getTextFieldsToBeSearched';
import { getTranslation } from '../../../../utilities/getTranslation';
import Pill from '../Pill';
import Chevron from '../../icons/Chevron';
import EditMany from '../EditMany';
import DeleteMany from '../DeleteMany';
import PublishMany from '../PublishMany';
import UnpublishMany from '../UnpublishMany';
import './index.scss';
@@ -26,6 +33,7 @@ const ListControls: React.FC<Props> = (props) => {
handleSortChange,
handleWhereChange,
modifySearchQuery = true,
resetParams,
collection: {
fields,
admin: {
@@ -45,6 +53,7 @@ const ListControls: React.FC<Props> = (props) => {
const [textFieldsToBeSearched] = useState(getTextFieldsToBeSearched(listSearchableFields, fields));
const [visibleDrawer, setVisibleDrawer] = useState<'where' | 'sort' | 'columns'>(shouldInitializeWhereOpened ? 'where' : undefined);
const { t, i18n } = useTranslation('general');
const { breakpoints: { s: smallBreak } } = useWindowInfo();
return (
<div className={baseClass}>
@@ -58,26 +67,44 @@ const ListControls: React.FC<Props> = (props) => {
/>
<div className={`${baseClass}__buttons`}>
<div className={`${baseClass}__buttons-wrap`}>
{ !smallBreak && (
<React.Fragment>
<EditMany
collection={collection}
resetParams={resetParams}
/>
<PublishMany
collection={collection}
resetParams={resetParams}
/>
<UnpublishMany
collection={collection}
resetParams={resetParams}
/>
<DeleteMany
collection={collection}
resetParams={resetParams}
/>
</React.Fragment>
)}
{enableColumns && (
<Button
className={`${baseClass}__toggle-columns`}
buttonStyle={visibleDrawer === 'columns' ? undefined : 'secondary'}
<Pill
pillStyle="dark"
className={`${baseClass}__toggle-columns ${visibleDrawer === 'columns' ? `${baseClass}__buttons-active` : ''}`}
onClick={() => setVisibleDrawer(visibleDrawer !== 'columns' ? 'columns' : undefined)}
icon="chevron"
iconStyle="none"
icon={<Chevron />}
>
{t('columns')}
</Button>
</Pill>
)}
<Button
className={`${baseClass}__toggle-where`}
buttonStyle={visibleDrawer === 'where' ? undefined : 'secondary'}
<Pill
pillStyle="dark"
className={`${baseClass}__toggle-where ${visibleDrawer === 'where' ? `${baseClass}__buttons-active` : ''}`}
onClick={() => setVisibleDrawer(visibleDrawer !== 'where' ? 'where' : undefined)}
icon="chevron"
iconStyle="none"
icon={<Chevron />}
>
{t('filters')}
</Button>
</Pill>
{enableSort && (
<Button
className={`${baseClass}__toggle-sort`}

View File

@@ -1,6 +1,7 @@
import { Where } from '../../../../types';
import { SanitizedCollectionConfig } from '../../../../collections/config/types';
import { Column } from '../Table/types';
import type { Props as ListProps } from '../../views/collections/List/types';
export type Props = {
enableColumns?: boolean
@@ -9,6 +10,7 @@ export type Props = {
handleSortChange?: (sort: string) => void
handleWhereChange?: (where: Where) => void
collection: SanitizedCollectionConfig
resetParams?: ListProps['resetParams']
}
export type ListControls = {

View File

@@ -222,16 +222,6 @@ export const ListDrawerContent: React.FC<ListDrawerProps> = ({
hasCreatePermission,
disableEyebrow: true,
modifySearchParams: false,
onCardClick: (doc) => {
if (typeof onSelect === 'function') {
onSelect({
docID: doc.id,
collectionConfig: selectedCollectionConfig,
});
}
closeModal(drawerSlug);
},
disableCardLink: true,
handleSortChange: setSort,
handleWhereChange: setWhere,
handlePageChange: setPage,

View File

@@ -0,0 +1,19 @@
@import '../../../scss/styles.scss';
.list-selection {
margin-left: auto;
color: var(--theme-elevation-500);
&__button {
color: var(--theme-elevation-500);
background: unset;
border: none;
text-decoration: underline;
cursor: pointer;
}
@include small-break {
margin-bottom: base(.5);
}
}

View File

@@ -0,0 +1,41 @@
import React, { Fragment } from 'react';
import { useTranslation } from 'react-i18next';
import { SelectAllStatus, useSelection } from '../../views/collections/List/SelectionProvider';
import './index.scss';
const baseClass = 'list-selection';
type Props = {
label: string
}
const ListSelection: React.FC<Props> = ({ label }) => {
const { toggleAll, count, totalDocs, selectAll } = useSelection();
const { t } = useTranslation('general');
if (count === 0) {
return null;
}
return (
<div className={baseClass}>
<span>{t('selectedCount', { label, count })}</span>
{ selectAll !== SelectAllStatus.AllAvailable && (
<Fragment>
{' '}
&mdash;
<button
className={`${baseClass}__button`}
type="button"
onClick={() => toggleAll(true)}
aria-label={t('selectAll', { label, count })}
>
{t('selectAll', { label, count: totalDocs })}
</button>
</Fragment>
) }
</div>
);
};
export default ListSelection;

View File

@@ -0,0 +1,17 @@
@import '../../../scss/styles.scss';
.publish-many {
@include blur-bg;
display: flex;
align-items: center;
height: 100%;
&__template {
z-index: 1;
position: relative;
}
.btn {
margin-right: $baseline;
}
}

View File

@@ -0,0 +1,123 @@
import React, { useState, useCallback } from 'react';
import { toast } from 'react-toastify';
import { Modal, useModal } from '@faceless-ui/modal';
import { useTranslation } from 'react-i18next';
import { useConfig } from '../../utilities/Config';
import Button from '../Button';
import MinimalTemplate from '../../templates/Minimal';
import { requests } from '../../../api';
import { Props } from './types';
import { SelectAllStatus, useSelection } from '../../views/collections/List/SelectionProvider';
import { getTranslation } from '../../../../utilities/getTranslation';
import Pill from '../Pill';
import { useAuth } from '../../utilities/Auth';
import './index.scss';
const baseClass = 'publish-many';
const PublishMany: React.FC<Props> = (props) => {
const {
resetParams,
collection: {
slug,
labels: {
plural,
},
versions,
} = {},
} = props;
const { serverURL, routes: { api } } = useConfig();
const { permissions } = useAuth();
const { toggleModal } = useModal();
const { t, i18n } = useTranslation('version');
const { selectAll, count, getQueryParams } = useSelection();
const [submitted, setSubmitted] = useState(false);
const collectionPermissions = permissions?.collections?.[slug];
const hasPermission = collectionPermissions?.update?.permission;
const modalSlug = `publish-${slug}`;
const addDefaultError = useCallback(() => {
toast.error(t('error:unknown'));
}, [t]);
const handlePublish = useCallback(() => {
setSubmitted(true);
requests.patch(`${serverURL}${api}/${slug}${getQueryParams({ _status: { not_equals: 'published' } })}`, {
body: JSON.stringify({
_status: 'published',
}),
headers: {
'Content-Type': 'application/json',
'Accept-Language': i18n.language,
},
}).then(async (res) => {
try {
const json = await res.json();
toggleModal(modalSlug);
if (res.status < 400) {
toast.success(t('general:updatedSuccessfully'));
resetParams({ page: selectAll ? 1 : undefined });
return null;
}
if (json.errors) {
json.errors.forEach((error) => toast.error(error.message));
} else {
addDefaultError();
}
return false;
} catch (e) {
return addDefaultError();
}
});
}, [addDefaultError, api, getQueryParams, i18n.language, modalSlug, resetParams, selectAll, serverURL, slug, t, toggleModal]);
if (!(versions?.drafts) || (selectAll === SelectAllStatus.None || !hasPermission)) {
return null;
}
return (
<React.Fragment>
<Pill
className={`${baseClass}__toggle`}
onClick={() => {
setSubmitted(false);
toggleModal(modalSlug);
}}
>
{t('publish')}
</Pill>
<Modal
slug={modalSlug}
className={baseClass}
>
<MinimalTemplate className={`${baseClass}__template`}>
<h1>{t('confirmPublish')}</h1>
<p>
{t('aboutToPublishSelection', { label: getTranslation(plural, i18n) })}
</p>
<Button
id="confirm-cancel"
buttonStyle="secondary"
type="button"
onClick={submitted ? undefined : () => toggleModal(modalSlug)}
>
{t('general:cancel')}
</Button>
<Button
onClick={submitted ? undefined : handlePublish}
id="confirm-publish"
>
{submitted ? t('publishing') : t('general:confirm')}
</Button>
</MinimalTemplate>
</Modal>
</React.Fragment>
);
};
export default PublishMany;

View File

@@ -0,0 +1,7 @@
import { SanitizedCollectionConfig } from '../../../../collections/config/types';
import type { Props as ListProps } from '../../views/collections/List/types';
export type Props = {
collection: SanitizedCollectionConfig,
resetParams: ListProps['resetParams'],
}

View File

@@ -7,10 +7,20 @@
position: absolute;
top: 50%;
transform: translateY(-50%);
right: base(.5);
left: base(.5);
}
&__input {
@include formInput;
box-shadow: none;
padding-left: base(2);
background-color: var(--theme-elevation-50);
border: none;
&:not(:disabled) {
&:hover, &:focus {
box-shadow: none;
}
}
}
}

View File

@@ -1,53 +1,25 @@
import React from 'react';
import type { TFunction } from 'react-i18next';
import Cell from '../../views/collections/List/Cell';
import SortColumn from '../SortColumn';
import { SanitizedCollectionConfig } from '../../../../collections/config/types';
import { Column } from '../Table/types';
import { Field, fieldIsPresentationalOnly } from '../../../../fields/config/types';
import { fieldIsPresentationalOnly } from '../../../../fields/config/types';
import flattenFields from '../../../../utilities/flattenTopLevelFields';
import { Props as CellProps } from '../../views/collections/List/Cell/types';
import SelectAll from '../../views/collections/List/SelectAll';
import SelectRow from '../../views/collections/List/SelectRow';
const buildColumns = ({
collection,
columns,
t,
cellProps,
}: {
collection: SanitizedCollectionConfig,
columns: Pick<Column, 'accessor' | 'active'>[],
t: TFunction,
cellProps: Partial<CellProps>[]
}): Column[] => {
// only insert each base field if it doesn't already exist in the collection
const baseFields: Field[] = [
{
name: 'id',
type: 'text',
label: 'ID',
},
{
name: 'updatedAt',
type: 'date',
label: t('updatedAt'),
},
{
name: 'createdAt',
type: 'date',
label: t('createdAt'),
},
];
const combinedFields = baseFields.reduce((acc, field) => {
// if the field already exists in the collection, don't add it
if (acc.find((f) => 'name' in f && 'name' in field && f.name === field.name)) return acc;
return [...acc, field];
}, collection.fields);
const flattenedFields = flattenFields(combinedFields, true);
// sort the fields to the order of activeColumns
const sortedFields = flattenedFields.sort((a, b) => {
const sortedFields = flattenFields(collection.fields, true).sort((a, b) => {
const aIndex = columns.findIndex((column) => column.accessor === a.name);
const bIndex = columns.findIndex((column) => column.accessor === b.name);
if (aIndex === -1 && bIndex === -1) return 0;
@@ -97,6 +69,23 @@ const buildColumns = ({
};
});
cols.unshift({
active: true,
label: null,
name: '',
accessor: '_select',
components: {
Heading: (
<SelectAll />
),
renderCell: (rowData) => (
<SelectRow
id={rowData.id}
/>
),
},
});
return cols;
};

View File

@@ -1,4 +1,3 @@
import { TFunction } from 'react-i18next';
import { SanitizedCollectionConfig } from '../../../../collections/config/types';
import { Column } from '../Table/types';
import buildColumns from './buildColumns';
@@ -9,7 +8,6 @@ type TOGGLE = {
type: 'toggle',
payload: {
column: string
t: TFunction
collection: SanitizedCollectionConfig
cellProps: Partial<CellProps>[]
}
@@ -19,7 +17,6 @@ type SET = {
type: 'set',
payload: {
columns: Pick<Column, 'accessor' | 'active'>[]
t: TFunction
collection: SanitizedCollectionConfig
cellProps: Partial<CellProps>[]
}
@@ -30,7 +27,6 @@ type MOVE = {
payload: {
fromIndex: number
toIndex: number
t: TFunction
collection: SanitizedCollectionConfig
cellProps: Partial<CellProps>[]
}
@@ -43,7 +39,6 @@ export const columnReducer = (state: Column[], action: Action): Column[] => {
case 'toggle': {
const {
column,
t,
collection,
cellProps,
} = action.payload;
@@ -62,7 +57,6 @@ export const columnReducer = (state: Column[], action: Action): Column[] => {
return buildColumns({
columns: withToggledColumn,
collection,
t,
cellProps,
});
}
@@ -70,7 +64,6 @@ export const columnReducer = (state: Column[], action: Action): Column[] => {
const {
fromIndex,
toIndex,
t,
collection,
cellProps,
} = action.payload;
@@ -82,14 +75,12 @@ export const columnReducer = (state: Column[], action: Action): Column[] => {
return buildColumns({
columns: withMovedColumn,
collection,
t,
cellProps,
});
}
case 'set': {
const {
columns,
t,
collection,
cellProps,
} = action.payload;
@@ -97,7 +88,6 @@ export const columnReducer = (state: Column[], action: Action): Column[] => {
return buildColumns({
columns,
collection,
t,
cellProps,
});
}

View File

@@ -1,4 +1,4 @@
import React, { useCallback, useEffect, useReducer, createContext, useContext, useRef } from 'react';
import React, { useCallback, useEffect, useReducer, createContext, useContext, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { SanitizedCollectionConfig } from '../../../../collections/config/types';
import { usePreferences } from '../../utilities/Preferences';
@@ -8,6 +8,8 @@ import buildColumns from './buildColumns';
import { Action, columnReducer } from './columnReducer';
import getInitialColumnState from './getInitialColumns';
import { Props as CellProps } from '../../views/collections/List/Cell/types';
import formatFields from '../../views/collections/List/formatFields';
import { Field } from '../../../../fields/config/types';
export interface ITableColumns {
columns: Column[]
@@ -33,21 +35,22 @@ export const TableColumnsProvider: React.FC<{
cellProps,
collection,
collection: {
fields,
admin: {
useAsTitle,
defaultColumns,
},
},
}) => {
const { t } = useTranslation('general');
const preferenceKey = `${collection.slug}-list`;
const prevCollection = useRef<SanitizedCollectionConfig['slug']>();
const hasInitialized = useRef(false);
const { getPreference, setPreference } = usePreferences();
const { t } = useTranslation();
const [formattedFields] = useState<Field[]>(() => formatFields(collection, t));
const [tableColumns, dispatchTableColumns] = useReducer(columnReducer, {}, () => {
const initialColumns = getInitialColumnState(fields, useAsTitle, defaultColumns);
const initialColumns = getInitialColumnState(formattedFields, useAsTitle, defaultColumns);
return buildColumns({
collection,
columns: initialColumns.map((column) => ({
@@ -55,7 +58,6 @@ export const TableColumnsProvider: React.FC<{
active: true,
})),
cellProps,
t,
});
});
@@ -72,7 +74,7 @@ export const TableColumnsProvider: React.FC<{
const currentPreferences = await getPreference<ListPreferences>(preferenceKey);
prevCollection.current = collection.slug;
const initialColumns = getInitialColumnState(fields, useAsTitle, defaultColumns);
const initialColumns = getInitialColumnState(formattedFields, useAsTitle, defaultColumns);
const newCols = currentPreferences?.columns || initialColumns;
dispatchTableColumns({
@@ -89,8 +91,7 @@ export const TableColumnsProvider: React.FC<{
}
return column;
}),
t,
collection,
collection: { ...collection, fields: formatFields(collection, t) },
cellProps,
},
});
@@ -100,7 +101,7 @@ export const TableColumnsProvider: React.FC<{
};
sync();
}, [preferenceKey, setPreference, fields, tableColumns, getPreference, useAsTitle, defaultColumns, t, collection, cellProps]);
}, [preferenceKey, setPreference, tableColumns, getPreference, useAsTitle, defaultColumns, collection, cellProps, formattedFields, t]);
// /////////////////////////////////////
// Set preferences on column change
@@ -130,12 +131,11 @@ export const TableColumnsProvider: React.FC<{
dispatchTableColumns({
type: 'set',
payload: {
collection,
collection: { ...collection, fields: formatFields(collection, t) },
columns: columns.map((column) => ({
accessor: column,
active: true,
})),
t,
// onSelect,
cellProps,
},
@@ -153,8 +153,7 @@ export const TableColumnsProvider: React.FC<{
payload: {
fromIndex,
toIndex,
collection,
t,
collection: { ...collection, fields: formatFields(collection, t) },
cellProps,
},
});
@@ -165,8 +164,7 @@ export const TableColumnsProvider: React.FC<{
type: 'toggle',
payload: {
column,
collection,
t,
collection: { ...collection, fields: formatFields(collection, t) },
cellProps,
},
});

View File

@@ -0,0 +1,17 @@
@import '../../../scss/styles.scss';
.unpublish-many {
@include blur-bg;
display: flex;
align-items: center;
height: 100%;
&__template {
z-index: 1;
position: relative;
}
.btn {
margin-right: $baseline;
}
}

View File

@@ -0,0 +1,123 @@
import React, { useState, useCallback } from 'react';
import { toast } from 'react-toastify';
import { Modal, useModal } from '@faceless-ui/modal';
import { useTranslation } from 'react-i18next';
import { useConfig } from '../../utilities/Config';
import Button from '../Button';
import MinimalTemplate from '../../templates/Minimal';
import { requests } from '../../../api';
import { Props } from './types';
import { SelectAllStatus, useSelection } from '../../views/collections/List/SelectionProvider';
import { getTranslation } from '../../../../utilities/getTranslation';
import Pill from '../Pill';
import { useAuth } from '../../utilities/Auth';
import './index.scss';
const baseClass = 'unpublish-many';
const UnpublishMany: React.FC<Props> = (props) => {
const {
resetParams,
collection: {
slug,
labels: {
plural,
},
versions,
} = {},
} = props;
const { serverURL, routes: { api } } = useConfig();
const { permissions } = useAuth();
const { toggleModal } = useModal();
const { t, i18n } = useTranslation('version');
const { selectAll, count, getQueryParams } = useSelection();
const [submitted, setSubmitted] = useState(false);
const collectionPermissions = permissions?.collections?.[slug];
const hasPermission = collectionPermissions?.update?.permission;
const modalSlug = `unpublish-${slug}`;
const addDefaultError = useCallback(() => {
toast.error(t('error:unknown'));
}, [t]);
const handleUnpublish = useCallback(() => {
setSubmitted(true);
requests.patch(`${serverURL}${api}/${slug}${getQueryParams({ _status: { not_equals: 'draft' } })}`, {
body: JSON.stringify({
_status: 'draft',
}),
headers: {
'Content-Type': 'application/json',
'Accept-Language': i18n.language,
},
}).then(async (res) => {
try {
const json = await res.json();
toggleModal(modalSlug);
if (res.status < 400) {
toast.success(t('general:updatedSuccessfully'));
resetParams({ page: selectAll ? 1 : undefined });
return null;
}
if (json.errors) {
json.errors.forEach((error) => toast.error(error.message));
} else {
addDefaultError();
}
return false;
} catch (e) {
return addDefaultError();
}
});
}, [addDefaultError, api, getQueryParams, i18n.language, modalSlug, resetParams, selectAll, serverURL, slug, t, toggleModal]);
if (!(versions?.drafts) || (selectAll === SelectAllStatus.None || !hasPermission)) {
return null;
}
return (
<React.Fragment>
<Pill
className={`${baseClass}__toggle`}
onClick={() => {
setSubmitted(false);
toggleModal(modalSlug);
}}
>
{t('unpublish')}
</Pill>
<Modal
slug={modalSlug}
className={baseClass}
>
<MinimalTemplate className={`${baseClass}__template`}>
<h1>{t('confirmUnpublish')}</h1>
<p>
{t('aboutToUnpublishSelection', { label: getTranslation(plural, i18n) })}
</p>
<Button
id="confirm-cancel"
buttonStyle="secondary"
type="button"
onClick={submitted ? undefined : () => toggleModal(modalSlug)}
>
{t('general:cancel')}
</Button>
<Button
onClick={submitted ? undefined : handleUnpublish}
id="confirm-unpublish"
>
{submitted ? t('unpublishing') : t('general:confirm')}
</Button>
</MinimalTemplate>
</Modal>
</React.Fragment>
);
};
export default UnpublishMany;

View File

@@ -0,0 +1,7 @@
import { SanitizedCollectionConfig } from '../../../../collections/config/types';
import type { Props as ListProps } from '../../views/collections/List/types';
export type Props = {
collection: SanitizedCollectionConfig,
resetParams: ListProps['resetParams'],
}

View File

@@ -1,32 +0,0 @@
@import '../../../scss/styles.scss';
.upload-gallery {
list-style: none;
padding: 0;
margin: base(2) -#{base(.5)};
width: calc(100% + #{$baseline});
display: flex;
flex-wrap: wrap;
li {
min-width: 0;
width: 16.66%;
}
.thumbnail-card {
margin: base(.5);
max-width: initial;
}
@include mid-break {
li {
width: 33.33%;
}
}
@include small-break {
li {
width: 50%;
}
}
}

View File

@@ -1,31 +0,0 @@
import React from 'react';
import { Props } from './types';
import { ThumbnailCard } from '../ThumbnailCard';
import './index.scss';
const baseClass = 'upload-gallery';
const UploadGallery: React.FC<Props> = (props) => {
const { docs, onCardClick, collection } = props;
if (docs && docs.length > 0) {
return (
<ul className={baseClass}>
{docs.map((doc) => (
<li key={String(doc.id)}>
<ThumbnailCard
doc={doc}
collection={collection}
onClick={() => onCardClick(doc)}
/>
</li>
))}
</ul>
);
}
return null;
};
export default UploadGallery;

View File

@@ -1,7 +0,0 @@
import { SanitizedCollectionConfig } from '../../../../collections/config/types';
export type Props = {
docs?: Record<string, unknown>[],
collection: SanitizedCollectionConfig,
onCardClick: (doc) => void,
}

View File

@@ -0,0 +1,11 @@
@import '../../../scss/styles';
.icon--line {
width: $baseline;
height: $baseline;
.stroke {
stroke: var(--theme-elevation-800);
stroke-width: $style-stroke-width;
}
}

View File

@@ -0,0 +1,21 @@
import React from 'react';
import './index.scss';
const Line: React.FC = () => (
<svg
className="icon icon--line"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 25 25"
>
<line
x1="8.05164"
y1="12.594"
x2="16.468"
y2="12.594"
className="stroke"
/>
</svg>
);
export default Line;

View File

@@ -0,0 +1,17 @@
@import '../../../../../../../scss/styles.scss';
.upload-cell {
display: flex;
flex-wrap: nowrap;
margin: base(-.25) 0;
.thumbnail {
max-width: base(3);
height: base(3);
}
&__filename {
align-self: center;
margin-left: base(1);
}
}

View File

@@ -0,0 +1,32 @@
import React from 'react';
import { Link } from 'react-router-dom';
import Thumbnail from '../../../../../../elements/Thumbnail';
import type { Props } from './types';
import { useConfig } from '../../../../../../utilities/Config';
import './index.scss';
const baseClass = 'upload-cell';
const UploadCell:React.FC<Props> = ({ rowData, cellData, collection }: Props) => {
const { routes: { admin } } = useConfig();
return (
<Link
className={baseClass}
to={`${admin}/collections/${collection.slug}/${rowData.id}`}
>
<Thumbnail
size="small"
doc={{
...rowData,
filename: cellData,
}}
collection={collection}
/>
<span className={`${baseClass}__filename`}>{ String(cellData) }</span>
</Link>
);
};
export default UploadCell;

View File

@@ -0,0 +1,6 @@
import { SanitizedCollectionConfig } from '../../../../../../../../collections/config/types';
import { Props as CellProps } from '../../types';
export type Props = CellProps & {
collection: SanitizedCollectionConfig
}

View File

@@ -1,11 +1,10 @@
import React, { Fragment } from 'react';
import { useHistory } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { useConfig } from '../../../utilities/Config';
import UploadGallery from '../../../elements/UploadGallery';
import { useWindowInfo } from '@faceless-ui/window-info';
import Eyebrow from '../../../elements/Eyebrow';
import Paginator from '../../../elements/Paginator';
import ListControls from '../../../elements/ListControls';
import ListSelection from '../../../elements/ListSelection';
import Pill from '../../../elements/Pill';
import Button from '../../../elements/Button';
import { Table } from '../../../elements/Table';
@@ -17,6 +16,11 @@ import { Gutter } from '../../../elements/Gutter';
import { RelationshipProvider } from './RelationshipProvider';
import { getTranslation } from '../../../../../utilities/getTranslation';
import { StaggeredShimmers } from '../../../elements/ShimmerEffect';
import { SelectionProvider } from './SelectionProvider';
import EditMany from '../../../elements/EditMany';
import DeleteMany from '../../../elements/DeleteMany';
import PublishMany from '../../../elements/PublishMany';
import UnpublishMany from '../../../elements/UnpublishMany';
import './index.scss';
@@ -26,8 +30,6 @@ const DefaultList: React.FC<Props> = (props) => {
const {
collection,
collection: {
upload,
slug,
labels: {
singular: singularLabel,
plural: pluralLabel,
@@ -42,17 +44,15 @@ const DefaultList: React.FC<Props> = (props) => {
hasCreatePermission,
disableEyebrow,
modifySearchParams,
disableCardLink,
onCardClick,
handleSortChange,
handleWhereChange,
handlePageChange,
handlePerPageChange,
customHeader,
resetParams,
} = props;
const { routes: { admin } } = useConfig();
const history = useHistory();
const { breakpoints: { s: smallBreak } } = useWindowInfo();
const { t, i18n } = useTranslation('general');
return (
@@ -60,117 +60,135 @@ const DefaultList: React.FC<Props> = (props) => {
<Meta
title={getTranslation(collection.labels.plural, i18n)}
/>
{!disableEyebrow && (
<Eyebrow />
)}
<Gutter className={`${baseClass}__wrap`}>
<header className={`${baseClass}__header`}>
{customHeader && customHeader}
{!customHeader && (
<Fragment>
<h1>
{getTranslation(pluralLabel, i18n)}
</h1>
{hasCreatePermission && (
<Pill to={newDocumentURL}>
{t('createNew')}
</Pill>
)}
{description && (
<div className={`${baseClass}__sub-header`}>
<ViewDescription description={description} />
</div>
)}
</Fragment>
)}
</header>
<ListControls
collection={collection}
enableColumns={Boolean(!upload)}
enableSort={Boolean(upload)}
modifySearchQuery={modifySearchParams}
handleSortChange={handleSortChange}
handleWhereChange={handleWhereChange}
/>
{!data.docs && (
<StaggeredShimmers
className={[
`${baseClass}__shimmer`,
upload ? `${baseClass}__shimmer--uploads` : `${baseClass}__shimmer--rows`,
].filter(Boolean).join(' ')}
count={6}
width={upload ? 'unset' : '100%'}
<SelectionProvider
docs={data.docs}
totalDocs={data.totalDocs}
>
{!disableEyebrow && (
<Eyebrow />
)}
<Gutter className={`${baseClass}__wrap`}>
<header className={`${baseClass}__header`}>
{customHeader && customHeader}
{!customHeader && (
<Fragment>
<h1>
{getTranslation(pluralLabel, i18n)}
</h1>
{hasCreatePermission && (
<Pill to={newDocumentURL}>
{t('createNew')}
</Pill>
)}
{!smallBreak && (
<ListSelection
label={getTranslation(collection.labels.plural, i18n)}
/>
)}
{description && (
<div className={`${baseClass}__sub-header`}>
<ViewDescription description={description} />
</div>
)}
</Fragment>
)}
</header>
<ListControls
collection={collection}
modifySearchQuery={modifySearchParams}
handleSortChange={handleSortChange}
handleWhereChange={handleWhereChange}
resetParams={resetParams}
/>
)}
{(data.docs && data.docs.length > 0) && (
<React.Fragment>
{!upload && (
<RelationshipProvider>
<Table data={data.docs} />
</RelationshipProvider>
)}
{upload && (
<UploadGallery
docs={data.docs}
collection={collection}
onCardClick={(doc) => {
if (typeof onCardClick === 'function') onCardClick(doc);
if (!disableCardLink) history.push(`${admin}/collections/${slug}/${doc.id}`);
}}
/>
)}
</React.Fragment>
)}
{data.docs && data.docs.length === 0 && (
<div className={`${baseClass}__no-results`}>
<p>
{t('noResults', { label: getTranslation(pluralLabel, i18n) })}
</p>
{hasCreatePermission && newDocumentURL && (
<Button
el="link"
to={newDocumentURL}
>
{t('createNewLabel', { label: getTranslation(singularLabel, i18n) })}
</Button>
{!data.docs && (
<StaggeredShimmers
className={[`${baseClass}__shimmer`, `${baseClass}__shimmer--rows`].join(' ')}
count={6}
/>
)}
{(data.docs && data.docs.length > 0) && (
<RelationshipProvider>
<Table data={data.docs} />
</RelationshipProvider>
)}
{data.docs && data.docs.length === 0 && (
<div className={`${baseClass}__no-results`}>
<p>
{t('noResults', { label: getTranslation(pluralLabel, i18n) })}
</p>
{hasCreatePermission && newDocumentURL && (
<Button
el="link"
to={newDocumentURL}
>
{t('createNewLabel', { label: getTranslation(singularLabel, i18n) })}
</Button>
)}
</div>
)}
<div className={`${baseClass}__page-controls`}>
<Paginator
limit={data.limit}
totalPages={data.totalPages}
page={data.page}
hasPrevPage={data.hasPrevPage}
hasNextPage={data.hasNextPage}
prevPage={data.prevPage}
nextPage={data.nextPage}
numberOfNeighbors={1}
disableHistoryChange={modifySearchParams === false}
onChange={handlePageChange}
/>
{data?.totalDocs > 0 && (
<Fragment>
<div className={`${baseClass}__page-info`}>
{(data.page * data.limit) - (data.limit - 1)}
-
{data.totalPages > 1 && data.totalPages !== data.page ? (data.limit * data.page) : data.totalDocs}
{' '}
{t('of')}
{' '}
{data.totalDocs}
</div>
<PerPage
limits={collection?.admin?.pagination?.limits}
limit={limit}
modifySearchParams={modifySearchParams}
handleChange={handlePerPageChange}
resetPage={data.totalDocs <= data.pagingCounter}
/>
<div className={`${baseClass}__list-selection`}>
{smallBreak && (
<Fragment>
<ListSelection
label={getTranslation(collection.labels.plural, i18n)}
/>
<div className={`${baseClass}__list-selection-actions`}>
<EditMany
collection={collection}
resetParams={resetParams}
/>
<PublishMany
collection={collection}
resetParams={resetParams}
/>
<UnpublishMany
collection={collection}
resetParams={resetParams}
/>
<DeleteMany
collection={collection}
resetParams={resetParams}
/>
</div>
</Fragment>
)}
</div>
</Fragment>
)}
</div>
)}
<div className={`${baseClass}__page-controls`}>
<Paginator
limit={data.limit}
totalPages={data.totalPages}
page={data.page}
hasPrevPage={data.hasPrevPage}
hasNextPage={data.hasNextPage}
prevPage={data.prevPage}
nextPage={data.nextPage}
numberOfNeighbors={1}
disableHistoryChange={modifySearchParams === false}
onChange={handlePageChange}
/>
{data?.totalDocs > 0 && (
<Fragment>
<div className={`${baseClass}__page-info`}>
{(data.page * data.limit) - (data.limit - 1)}
-
{data.totalPages > 1 && data.totalPages !== data.page ? (data.limit * data.page) : data.totalDocs}
{' '}
{t('of')}
{' '}
{data.totalDocs}
</div>
<PerPage
limits={collection?.admin?.pagination?.limits}
limit={limit}
modifySearchParams={modifySearchParams}
handleChange={handlePerPageChange}
resetPage={data.totalDocs <= data.pagingCounter}
/>
</Fragment>
)}
</div>
</Gutter>
</Gutter>
</SelectionProvider>
</div>
);
};

View File

@@ -0,0 +1,30 @@
@import '../../../../../scss/styles.scss';
.select-all {
button {
@extend %btn-reset;
display: flex;
align-items: center;
cursor: pointer;
&:focus,
&:active {
outline: none;
}
&:hover {
svg {
opacity: .2;
}
}
}
&__input {
@include formInput;
padding: 0;
line-height: 0;
position: relative;
width: $baseline;
height: $baseline;
}
}

View File

@@ -0,0 +1,32 @@
import React from 'react';
import { SelectAllStatus, useSelection } from '../SelectionProvider';
import Check from '../../../../icons/Check';
import Line from '../../../../icons/Line';
import './index.scss';
const baseClass = 'select-all';
const SelectAll: React.FC = () => {
const { selectAll, toggleAll } = useSelection();
return (
<div className={baseClass}>
<button
type="button"
onClick={() => toggleAll()}
>
<span className={`${baseClass}__input`}>
{ (selectAll === SelectAllStatus.AllInPage || selectAll === SelectAllStatus.AllAvailable) && (
<Check />
)}
{ selectAll === SelectAllStatus.Some && (
<Line />
)}
</span>
</button>
</div>
);
};
export default SelectAll;

View File

@@ -0,0 +1,44 @@
@import '../../../../../scss/styles.scss';
.select-row {
button {
@extend %btn-reset;
display: flex;
align-items: center;
cursor: pointer;
&:focus,
&:active {
outline: none;
}
&:hover {
svg {
opacity: .2;
}
}
}
&__input {
@include formInput;
padding: 0;
line-height: 0;
position: relative;
width: $baseline;
height: $baseline;
svg {
opacity: 0;
}
}
&--checked {
button {
.select-row__input {
svg {
opacity: 1;
}
}
}
}
}

View File

@@ -0,0 +1,32 @@
import React from 'react';
import { useSelection } from '../SelectionProvider';
import Check from '../../../../icons/Check';
import './index.scss';
const baseClass = 'select-row';
const SelectRow: React.FC<{ id: string | number }> = ({ id }) => {
const { selected, setSelection } = useSelection();
return (
<div
className={[
baseClass,
(selected[id]) && `${baseClass}--checked`,
].filter(Boolean).join(' ')}
key={id}
>
<button
type="button"
onClick={() => setSelection(id)}
>
<span className={`${baseClass}__input`}>
<Check />
</span>
</button>
</div>
);
};
export default SelectRow;

View File

@@ -0,0 +1,157 @@
import React, {
createContext,
useCallback,
useContext,
useEffect,
useRef,
useState,
} from 'react';
import { useHistory } from 'react-router-dom';
import queryString from 'qs';
import { Where } from '../../../../../../types';
export enum SelectAllStatus {
AllAvailable = 'allAvailable',
AllInPage = 'allInPage',
Some = 'some',
None = 'none',
}
type SelectionContext = {
selected: Record<string | number, boolean>
setSelection: (id: string | number) => void
selectAll: SelectAllStatus
toggleAll: (allAvailable?: boolean) => void
totalDocs: number
count: number
getQueryParams: (additionalParams?: Where) => string
}
const Context = createContext({} as SelectionContext);
type Props = {
children: React.ReactNode
docs: any[]
totalDocs: number
}
export const SelectionProvider: React.FC<Props> = ({ children, docs = [], totalDocs }) => {
const contextRef = useRef({} as SelectionContext);
const history = useHistory();
const [selected, setSelected] = useState<SelectionContext['selected']>({});
const [selectAll, setSelectAll] = useState<SelectAllStatus>(SelectAllStatus.None);
const [count, setCount] = useState(0);
const toggleAll = useCallback((allAvailable = false) => {
const rows = {};
if (allAvailable) {
setSelectAll(SelectAllStatus.AllAvailable);
docs.forEach(({ id }) => {
rows[id] = true;
});
} else if (selectAll === SelectAllStatus.AllAvailable || selectAll === SelectAllStatus.AllInPage) {
setSelectAll(SelectAllStatus.None);
docs.forEach(({ id }) => {
rows[id] = false;
});
} else {
docs.forEach(({ id }) => {
rows[id] = selectAll !== SelectAllStatus.Some;
});
}
setSelected(rows);
}, [docs, selectAll]);
const setSelection = useCallback((id) => {
const isSelected = !selected[id];
const newSelected = {
...selected,
[id]: isSelected,
};
if (!isSelected) {
setSelectAll(SelectAllStatus.Some);
}
setSelected(newSelected);
}, [selected]);
const getQueryParams = useCallback((additionalParams?: Where): string => {
let where: Where;
if (selectAll === SelectAllStatus.AllAvailable) {
const params = queryString.parse(history.location.search, { ignoreQueryPrefix: true }).where as Where;
where = params || {
id: { not_equals: '' },
};
} else {
where = {
id: {
in: Object.keys(selected).filter((id) => selected[id]).map((id) => id),
},
};
}
if (additionalParams) {
where = {
and: [
{ ...additionalParams },
where,
],
};
}
return queryString.stringify({
where,
}, { addQueryPrefix: true });
}, [history.location.search, selectAll, selected]);
useEffect(() => {
if (selectAll === SelectAllStatus.AllAvailable) {
return;
}
let some = false;
let all = true;
Object.values(selected).forEach((val) => {
all = all && val;
some = some || val;
});
if (all) {
setSelectAll(SelectAllStatus.AllInPage);
} else if (some) {
setSelectAll(SelectAllStatus.Some);
} else {
setSelectAll(SelectAllStatus.None);
}
}, [docs, selectAll, selected]);
useEffect(() => {
const rows = {};
if (docs.length) {
docs.forEach(({ id }) => {
rows[id] = false;
});
setSelected(rows);
}
setSelectAll(SelectAllStatus.None);
}, [docs, history]);
useEffect(() => {
const newCount = selectAll === SelectAllStatus.AllAvailable ? totalDocs : Object.keys(selected).filter((id) => selected[id]).length;
setCount(newCount);
}, [selectAll, selected, totalDocs]);
contextRef.current = {
selectAll,
toggleAll,
selected,
setSelection,
totalDocs,
count,
getQueryParams,
};
return (
<Context.Provider value={contextRef.current}>
{children}
</Context.Provider>
);
};
export const useSelection = (): SelectionContext => useContext(Context);

View File

@@ -1,42 +1,70 @@
import { TFunction } from 'react-i18next';
import React from 'react';
import { SanitizedCollectionConfig } from '../../../../../collections/config/types';
import { Field, fieldAffectsData, fieldIsPresentationalOnly } from '../../../../../fields/config/types';
import UploadCell from './Cell/field-types/Upload';
import { Props } from './Cell/types';
const formatFields = (config: SanitizedCollectionConfig, t: TFunction): Field[] => {
const hasID = config.fields.findIndex((field) => fieldAffectsData(field) && field.name === 'id') > -1;
let fields: Field[] = config.fields.reduce((formatted, field) => {
const fields: Field[] = config.fields.reduce((formatted, field) => {
if (!fieldIsPresentationalOnly(field) && (field.hidden === true || field?.admin?.disabled === true)) {
return formatted;
}
if (config.upload && fieldAffectsData(field) && field.name === 'filename') {
const Cell: React.FC<Props> = (props) => (
<UploadCell
collection={config}
{...props}
/>
);
return [
...formatted,
{
...field,
admin: {
...field.admin,
components: {
...field.admin?.components || {},
Cell: field.admin?.components?.Cell || Cell,
},
},
},
];
}
return [
...formatted,
field,
];
}, hasID ? [] : [{ name: 'id', label: 'ID', type: 'text' }]);
}, hasID ? [] : [{
name: 'id',
label: 'ID',
type: 'text',
admin: {
disableBulkEdit: true,
},
}]);
if (config.timestamps) {
fields = fields.concat([
fields.push(
{
name: 'createdAt',
label: t('general:createdAt'),
type: 'date',
admin: {
disableBulkEdit: true,
},
}, {
name: 'updatedAt',
label: t('general:updatedAt'),
type: 'date',
admin: {
disableBulkEdit: true,
},
},
]);
}
if (config.upload) {
fields = fields.concat([
{
name: 'filename',
label: t('upload:fileName'),
type: 'text',
},
]);
);
}
return fields;

View File

@@ -37,6 +37,12 @@
table {
width: 100%;
overflow: auto;
#heading-_select,
.cell-_select {
min-width: unset;
width: auto;
}
}
}
@@ -55,31 +61,40 @@
margin-left: auto;
}
&__shimmer {
margin-top: base(1.75);
}
&__list-selection {
position: fixed;
bottom: 0;
z-index: 10;
padding: base(.75) 0;
width: 100%;
background-color: var(--theme-bg);
&__shimmer--rows {
>div {
margin-top: 8px;
.btn {
margin: 0 0 0 base(.5);
}
.btn {
background-color: var(--theme-elevation-100);
cursor: pointer;
padding: 0 base(.25);
border-radius: $style-radius-s;
&:hover {
background-color: var(--theme-elevation-200);
}
}
}
&__shimmer--uploads {
// match upload cards
margin: base(2) -#{base(.5)};
width: calc(100% + #{$baseline});
&__list-selection-actions {
display: flex;
flex-wrap: wrap;
gap: base(.25);
}
&__shimmer {
margin-top: base(1.75);
width: 100%;
>div {
min-width: 0;
width: calc(16.66%);
>div {
margin: base(.5);
padding-bottom: 110%;
}
margin-top: 8px;
}
}
@@ -111,19 +126,9 @@
width: 100%;
margin-bottom: $baseline;
}
&__shimmer--uploads {
>div {
width: 33.33%;
}
}
}
@include small-break {
&__shimmer--uploads {
>div {
width: 50%;
}
}
margin-bottom: base(3);
}
}

View File

@@ -1,4 +1,5 @@
import React, { useEffect, useState } from 'react';
import { v4 as uuid } from 'uuid';
import React, { useEffect, useState, useCallback } from 'react';
import { useHistory } from 'react-router-dom';
import queryString from 'qs';
import { useTranslation } from 'react-i18next';
@@ -9,10 +10,11 @@ import DefaultList from './Default';
import RenderCustomComponent from '../../../utilities/RenderCustomComponent';
import { useStepNav } from '../../../elements/StepNav';
import formatFields from './formatFields';
import { ListIndexProps, ListPreferences } from './types';
import { Props, ListIndexProps, ListPreferences } from './types';
import { usePreferences } from '../../../utilities/Preferences';
import { useSearchParams } from '../../../utilities/SearchParams';
import { Field } from '../../../../../fields/config/types';
import { TableColumnsProvider } from '../../../elements/TableColumns';
import type { Field } from '../../../../../fields/config/types';
const ListView: React.FC<ListIndexProps> = (props) => {
const {
@@ -48,7 +50,7 @@ const ListView: React.FC<ListIndexProps> = (props) => {
const collectionPermissions = permissions?.collections?.[slug];
const hasCreatePermission = collectionPermissions?.create?.permission;
const newDocumentURL = `${admin}/collections/${slug}/create`;
const [{ data }, { setParams: setFetchParams }] = usePayloadAPI(fetchURL, { initialParams: { page: 1 } });
const [{ data }, { setParams }] = usePayloadAPI(fetchURL, { initialParams: { page: 1 } });
useEffect(() => {
setStepNav([
@@ -62,27 +64,31 @@ const ListView: React.FC<ListIndexProps> = (props) => {
// Set up Payload REST API query params
// /////////////////////////////////////
useEffect(() => {
const params = {
const resetParams = useCallback<Props['resetParams']>((overrides = {}) => {
const params: Record<string, unknown> = {
depth: 0,
draft: 'true',
page: undefined,
sort: undefined,
where: undefined,
page: overrides?.page,
sort: overrides?.sort,
where: overrides?.where,
limit,
};
if (page) params.page = page;
if (sort) params.sort = sort;
if (where) params.where = where;
params.invoke = uuid();
setParams(params);
}, [limit, page, setParams, sort, where]);
useEffect(() => {
// Performance enhancement
// Setting the Fetch URL this way
// prevents a double-fetch
setFetchURL(`${serverURL}${api}/${slug}`);
setFetchParams(params);
}, [setFetchParams, page, sort, where, collection, limit, serverURL, api, slug]);
resetParams();
}, [api, resetParams, serverURL, slug]);
// /////////////////////////////////////
// Fetch preferences on first load
@@ -128,18 +134,41 @@ const ListView: React.FC<ListIndexProps> = (props) => {
})();
}, [sort, limit, preferenceKey, setPreference, getPreference]);
// /////////////////////////////////////
// Prevent going beyond page limit
// /////////////////////////////////////
useEffect(() => {
if (data?.totalDocs && data.pagingCounter > data.totalDocs) {
const params = queryString.parse(history.location.search, {
ignoreQueryPrefix: true,
depth: 0,
});
const newSearchQuery = queryString.stringify({
...params,
page: data.totalPages,
}, { addQueryPrefix: true });
history.replace({
search: newSearchQuery,
});
}
}, [data, history, resetParams]);
return (
<RenderCustomComponent
DefaultComponent={DefaultList}
CustomComponent={CustomList}
componentProps={{
collection: { ...collection, fields },
newDocumentURL,
hasCreatePermission,
data,
limit: limit || defaultLimit,
}}
/>
<TableColumnsProvider collection={collection}>
<RenderCustomComponent
DefaultComponent={DefaultList}
CustomComponent={CustomList}
componentProps={{
collection: { ...collection, fields },
newDocumentURL,
hasCreatePermission,
data,
limit: limit || defaultLimit,
resetParams,
}}
/>
</TableColumnsProvider>
);
};

View File

@@ -1,3 +1,4 @@
import { Where } from '../../../../../types';
import { SanitizedCollectionConfig } from '../../../../../collections/config/types';
import { PaginatedDocs } from '../../../../../mongoose/types';
import { Props as ListControlsProps } from '../../../elements/ListControls/types';
@@ -11,15 +12,16 @@ export type Props = {
setListControls: (controls: unknown) => void
setSort: (sort: string) => void
toggleColumn: (column: string) => void
resetParams: (overrides?: { page?: number, sort?: string, where?: Where }) => void
hasCreatePermission: boolean
setLimit: (limit: number) => void
limit: number
disableEyebrow?: boolean
modifySearchParams?: boolean
onCardClick?: (doc: any) => void
disableCardLink?: boolean
handleSortChange?: ListControlsProps['handleSortChange']
handleWhereChange?: ListControlsProps['handleWhereChange']
handleDelete?: () => void
handlePageChange?: PaginatorProps['onChange']
handlePerPageChange?: PerPageProps['handleChange']
onCreateNewClick?: () => void

View File

@@ -16,9 +16,11 @@ import findVersionByID from './requestHandlers/findVersionByID';
import restoreVersion from './requestHandlers/restoreVersion';
import deleteHandler from './requestHandlers/delete';
import findByID from './requestHandlers/findByID';
import update, { deprecatedUpdate } from './requestHandlers/update';
import update from './requestHandlers/update';
import updateByID, { deprecatedUpdate } from './requestHandlers/updateByID';
import logoutHandler from '../auth/requestHandlers/logout';
import docAccessRequestHandler from './requestHandlers/docAccess';
import deleteByID from './requestHandlers/deleteByID';
const buildEndpoints = (collection: SanitizedCollectionConfig): Endpoint[] => {
let { endpoints } = collection;
@@ -131,10 +133,15 @@ const buildEndpoints = (collection: SanitizedCollectionConfig): Endpoint[] => {
handler: deprecatedUpdate,
},
{
path: '/:id',
path: '/',
method: 'patch',
handler: update,
},
{
path: '/:id',
method: 'patch',
handler: updateByID,
},
{
path: '/:id',
method: 'get',
@@ -143,6 +150,11 @@ const buildEndpoints = (collection: SanitizedCollectionConfig): Endpoint[] => {
{
path: '/:id',
method: 'delete',
handler: deleteByID,
},
{
path: '/',
method: 'delete',
handler: deleteHandler,
},
]);

View File

@@ -9,6 +9,7 @@ import { PayloadRequest } from '../../express/types';
import { IncomingAuthType, Auth } from '../../auth/types';
import { IncomingUploadType, Upload } from '../../uploads/types';
import { IncomingCollectionVersions, SanitizedCollectionVersions } from '../../versions/types';
import { Config as GeneratedTypes } from '../../generated-types';
type Register<T = any> = (doc: T, password: string) => T;
@@ -101,13 +102,13 @@ export type AfterReadHook<T extends TypeWithID = any> = (args: {
export type BeforeDeleteHook = (args: {
req: PayloadRequest;
id: string;
id: string | number;
}) => any;
export type AfterDeleteHook<T extends TypeWithID = any> = (args: {
doc: T;
req: PayloadRequest;
id: string;
id: string | number;
}) => any;
export type AfterErrorHook = (err: Error, res: unknown) => { response: any, status: number } | void;
@@ -320,6 +321,14 @@ export type Collection = {
}
};
export type BulkOperationResult<TSlug extends keyof GeneratedTypes['collections']> = {
docs: GeneratedTypes['collections'][TSlug][],
errors: {
message: string
id: GeneratedTypes['collections'][TSlug]['id']
}[]
}
export type AuthCollection = {
Model: AuthCollectionModel;
config: SanitizedCollectionConfig;

View File

@@ -3,7 +3,7 @@ import { Config as GeneratedTypes } from 'payload/generated-types';
import { Response } from 'express';
import { PayloadRequest } from '../../../express/types';
import { Collection } from '../../config/types';
import deleteOperation from '../../operations/delete';
import deleteByID from '../../operations/deleteByID';
export type Resolver<TSlug extends keyof GeneratedTypes['collections']> = (
_: unknown,
@@ -31,7 +31,7 @@ export default function getDeleteResolver<TSlug extends keyof GeneratedTypes['co
depth: 0,
};
const result = await deleteOperation(options);
const result = await deleteByID(options);
return result;
}

View File

@@ -2,7 +2,7 @@
import { Response } from 'express';
import { Config as GeneratedTypes } from 'payload/generated-types';
import { Collection } from '../../config/types';
import update from '../../operations/update';
import updateByID from '../../operations/updateByID';
import { PayloadRequest } from '../../../express/types';
export type Resolver<TSlug extends keyof GeneratedTypes['collections']> = (_: unknown, args: {
@@ -35,7 +35,7 @@ export default function updateResolver<TSlug extends keyof GeneratedTypes['colle
autosave: args.autosave,
};
const result = await update<TSlug>(options);
const result = await updateByID<TSlug>(options);
return result;
}

View File

@@ -1,23 +1,21 @@
import fs from 'fs';
import path from 'path';
import { Config as GeneratedTypes } from 'payload/generated-types';
import httpStatus from 'http-status';
import { AccessResult } from '../../config/types';
import { PayloadRequest } from '../../express/types';
import sanitizeInternalFields from '../../utilities/sanitizeInternalFields';
import { NotFound, Forbidden, ErrorDeletingFile } from '../../errors';
import { APIError } from '../../errors';
import executeAccess from '../../auth/executeAccess';
import { BeforeOperationHook, Collection } from '../config/types';
import { Document, Where } from '../../types';
import { Where } from '../../types';
import { hasWhereAccessResult } from '../../auth/types';
import { FileData } from '../../uploads/types';
import fileExists from '../../uploads/fileExists';
import { afterRead } from '../../fields/hooks/afterRead';
import { deleteCollectionVersions } from '../../versions/deleteCollectionVersions';
import { deleteAssociatedFiles } from '../../uploads/deleteAssociatedFiles';
export type Arguments = {
depth?: number
collection: Collection
id: string
where: Where
req: PayloadRequest
overrideAccess?: boolean
showHiddenFields?: boolean
@@ -25,7 +23,13 @@ export type Arguments = {
async function deleteOperation<TSlug extends keyof GeneratedTypes['collections']>(
incomingArgs: Arguments,
): Promise<GeneratedTypes['collections'][TSlug]> {
): Promise<{
docs: GeneratedTypes['collections'][TSlug][],
errors: {
message: string
id: GeneratedTypes['collections'][TSlug]['id']
}[]
}> {
let args = incomingArgs;
// /////////////////////////////////////
@@ -47,7 +51,7 @@ async function deleteOperation<TSlug extends keyof GeneratedTypes['collections']
Model,
config: collectionConfig,
},
id,
where,
req,
req: {
t,
@@ -62,166 +66,173 @@ async function deleteOperation<TSlug extends keyof GeneratedTypes['collections']
showHiddenFields,
} = args;
if (!where) {
throw new APIError('Missing \'where\' query of documents to delete.', httpStatus.BAD_REQUEST);
}
// /////////////////////////////////////
// Access
// /////////////////////////////////////
const accessResults = !overrideAccess ? await executeAccess({ req, id }, collectionConfig.access.delete) : true;
const hasWhereAccess = hasWhereAccessResult(accessResults);
// /////////////////////////////////////
// beforeDelete - Collection
// /////////////////////////////////////
await collectionConfig.hooks.beforeDelete.reduce(async (priorHook, hook) => {
await priorHook;
return hook({
req,
id,
});
}, Promise.resolve());
// /////////////////////////////////////
// Retrieve document
// /////////////////////////////////////
const queryToBuild: {
where: Where
} = {
const queryToBuild: { where?: Where } = {
where: {
and: [
{
id: {
equals: id,
},
},
],
and: [],
},
};
if (hasWhereAccessResult(accessResults)) {
(queryToBuild.where.and as Where[]).push(accessResults);
if (where) {
queryToBuild.where = {
and: [],
...where,
};
if (Array.isArray(where.AND)) {
queryToBuild.where.and = [
...queryToBuild.where.and,
...where.AND,
];
}
}
let accessResult: AccessResult;
if (!overrideAccess) {
accessResult = await executeAccess({ req }, collectionConfig.access.delete);
if (hasWhereAccessResult(accessResult)) {
queryToBuild.where.and.push(accessResult);
}
}
const query = await Model.buildQuery(queryToBuild, locale);
const docToDelete = await Model.findOne(query);
if (!docToDelete && !hasWhereAccess) throw new NotFound(t);
if (!docToDelete && hasWhereAccess) throw new Forbidden(t);
const resultToDelete = docToDelete.toJSON({ virtuals: true });
// /////////////////////////////////////
// Delete any associated files
// Retrieve documents
// /////////////////////////////////////
if (collectionConfig.upload) {
const { staticDir } = collectionConfig.upload;
const docs = await Model.find(query, {}, { lean: true });
const staticPath = path.resolve(config.paths.configDir, staticDir);
const errors = [];
const fileToDelete = `${staticPath}/${resultToDelete.filename}`;
/* eslint-disable no-param-reassign */
const promises = docs.map(async (doc) => {
let result;
if (await fileExists(fileToDelete)) {
fs.unlink(fileToDelete, (err) => {
if (err) {
throw new ErrorDeletingFile(t);
}
// custom id type reset
doc.id = doc._id;
doc = JSON.stringify(doc);
doc = JSON.parse(doc);
doc = sanitizeInternalFields(doc);
const { id } = doc;
try {
// /////////////////////////////////////
// beforeDelete - Collection
// /////////////////////////////////////
await collectionConfig.hooks.beforeDelete.reduce(async (priorHook, hook) => {
await priorHook;
return hook({
req,
id,
});
}, Promise.resolve());
await deleteAssociatedFiles({ config, collectionConfig, doc, t, overrideDelete: true });
// /////////////////////////////////////
// Delete document
// /////////////////////////////////////
await Model.deleteOne({ _id: id }, { lean: true });
// /////////////////////////////////////
// Delete versions
// /////////////////////////////////////
if (collectionConfig.versions) {
deleteCollectionVersions({
payload,
id,
slug: collectionConfig.slug,
});
}
// /////////////////////////////////////
// afterDelete - Collection
// /////////////////////////////////////
await collectionConfig.hooks.afterDelete.reduce(async (priorHook, hook) => {
await priorHook;
result = await hook({
req,
id,
doc,
}) || doc;
}, Promise.resolve());
// /////////////////////////////////////
// afterRead - Fields
// /////////////////////////////////////
result = await afterRead({
depth,
doc: result || doc,
entityConfig: collectionConfig,
overrideAccess,
req,
showHiddenFields,
});
// /////////////////////////////////////
// afterRead - Collection
// /////////////////////////////////////
await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => {
await priorHook;
result = await hook({
req,
doc: result || doc,
}) || result;
}, Promise.resolve());
// /////////////////////////////////////
// 8. Return results
// /////////////////////////////////////
return result;
} catch (error) {
errors.push({
message: error.message,
id: doc.id,
});
}
return null;
});
if (resultToDelete.sizes) {
Object.values(resultToDelete.sizes).forEach(async (size: FileData) => {
const sizeToDelete = `${staticPath}/${size.filename}`;
if (await fileExists(sizeToDelete)) {
fs.unlink(sizeToDelete, (err) => {
if (err) {
throw new ErrorDeletingFile(t);
}
});
}
});
}
}
// /////////////////////////////////////
// Delete document
// /////////////////////////////////////
const doc = await Model.findOneAndDelete({ _id: id });
let result: Document = doc.toJSON({ virtuals: true });
// custom id type reset
result.id = result._id;
result = JSON.stringify(result);
result = JSON.parse(result);
result = sanitizeInternalFields(result);
const awaitedDocs = await Promise.all(promises);
// /////////////////////////////////////
// Delete Preferences
// /////////////////////////////////////
if (collectionConfig.auth) {
await preferences.Model.deleteMany({ user: id, userCollection: collectionConfig.slug });
}
await preferences.Model.deleteMany({ key: `collection-${collectionConfig.slug}-${id}` });
// /////////////////////////////////////
// Delete versions
// /////////////////////////////////////
if (collectionConfig.versions) {
deleteCollectionVersions({
payload,
id,
slug: collectionConfig.slug,
preferences.Model.deleteMany({
user: { in: docs.map(({ id }) => id) },
userCollection: collectionConfig.slug,
});
}
preferences.Model.deleteMany({ key: { in: docs.map(({ id }) => `collection-${collectionConfig.slug}-${id}`) } });
// /////////////////////////////////////
// afterDelete - Collection
// /////////////////////////////////////
await collectionConfig.hooks.afterDelete.reduce(async (priorHook, hook) => {
await priorHook;
result = await hook({ req, id, doc: result }) || result;
}, Promise.resolve());
// /////////////////////////////////////
// afterRead - Fields
// /////////////////////////////////////
result = await afterRead({
depth,
doc: result,
entityConfig: collectionConfig,
overrideAccess,
req,
showHiddenFields,
});
// /////////////////////////////////////
// afterRead - Collection
// /////////////////////////////////////
await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => {
await priorHook;
result = await hook({
req,
doc: result,
}) || result;
}, Promise.resolve());
// /////////////////////////////////////
// 8. Return results
// /////////////////////////////////////
return result;
return {
docs: awaitedDocs.filter(Boolean),
errors,
};
}
export default deleteOperation;

View File

@@ -0,0 +1,191 @@
import { Config as GeneratedTypes } from 'payload/generated-types';
import { PayloadRequest } from '../../express/types';
import sanitizeInternalFields from '../../utilities/sanitizeInternalFields';
import { NotFound, Forbidden } from '../../errors';
import executeAccess from '../../auth/executeAccess';
import { BeforeOperationHook, Collection } from '../config/types';
import { Document, Where } from '../../types';
import { hasWhereAccessResult } from '../../auth/types';
import { afterRead } from '../../fields/hooks/afterRead';
import { deleteCollectionVersions } from '../../versions/deleteCollectionVersions';
import { deleteAssociatedFiles } from '../../uploads/deleteAssociatedFiles';
export type Arguments = {
depth?: number
collection: Collection
id: string | number
req: PayloadRequest
overrideAccess?: boolean
showHiddenFields?: boolean
}
async function deleteByID<TSlug extends keyof GeneratedTypes['collections']>(incomingArgs: Arguments): Promise<Document> {
let args = incomingArgs;
// /////////////////////////////////////
// beforeOperation - Collection
// /////////////////////////////////////
await args.collection.config.hooks.beforeOperation.reduce(async (priorHook: BeforeOperationHook | Promise<void>, hook: BeforeOperationHook) => {
await priorHook;
args = (await hook({
args,
operation: 'delete',
})) || args;
}, Promise.resolve());
const {
depth,
collection: {
Model,
config: collectionConfig,
},
id,
req,
req: {
t,
locale,
payload,
payload: {
config,
preferences,
},
},
overrideAccess,
showHiddenFields,
} = args;
// /////////////////////////////////////
// Access
// /////////////////////////////////////
const accessResults = !overrideAccess ? await executeAccess({ req, id }, collectionConfig.access.delete) : true;
const hasWhereAccess = hasWhereAccessResult(accessResults);
// /////////////////////////////////////
// beforeDelete - Collection
// /////////////////////////////////////
await collectionConfig.hooks.beforeDelete.reduce(async (priorHook, hook) => {
await priorHook;
return hook({
req,
id,
});
}, Promise.resolve());
// /////////////////////////////////////
// Retrieve document
// /////////////////////////////////////
const queryToBuild: {
where: Where
} = {
where: {
and: [
{
id: {
equals: id,
},
},
],
},
};
if (hasWhereAccessResult(accessResults)) {
(queryToBuild.where.and as Where[]).push(accessResults);
}
const query = await Model.buildQuery(queryToBuild, locale);
const docToDelete = await Model.findOne(query);
if (!docToDelete && !hasWhereAccess) throw new NotFound(t);
if (!docToDelete && hasWhereAccess) throw new Forbidden(t);
const resultToDelete = docToDelete.toJSON({ virtuals: true });
await deleteAssociatedFiles({ config, collectionConfig, doc: resultToDelete, t, overrideDelete: true });
// /////////////////////////////////////
// Delete document
// /////////////////////////////////////
const doc = await Model.findOneAndDelete({ _id: id });
let result: Document = doc.toJSON({ virtuals: true });
// custom id type reset
result.id = result._id;
result = JSON.stringify(result);
result = JSON.parse(result);
result = sanitizeInternalFields(result);
// /////////////////////////////////////
// Delete Preferences
// /////////////////////////////////////
if (collectionConfig.auth) {
await preferences.Model.deleteMany({ user: id, userCollection: collectionConfig.slug });
}
await preferences.Model.deleteMany({ key: `collection-${collectionConfig.slug}-${id}` });
// /////////////////////////////////////
// Delete versions
// /////////////////////////////////////
if (collectionConfig.versions) {
deleteCollectionVersions({
payload,
id,
slug: collectionConfig.slug,
});
}
// /////////////////////////////////////
// afterDelete - Collection
// /////////////////////////////////////
await collectionConfig.hooks.afterDelete.reduce(async (priorHook, hook) => {
await priorHook;
result = await hook({ req, id, doc: result }) || result;
}, Promise.resolve());
// /////////////////////////////////////
// afterRead - Fields
// /////////////////////////////////////
result = await afterRead({
depth,
doc: result,
entityConfig: collectionConfig,
overrideAccess,
req,
showHiddenFields,
});
// /////////////////////////////////////
// afterRead - Collection
// /////////////////////////////////////
await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => {
await priorHook;
result = await hook({
req,
doc: result,
}) || result;
}, Promise.resolve());
// /////////////////////////////////////
// 8. Return results
// /////////////////////////////////////
return result;
}
export default deleteByID;

View File

@@ -1,15 +1,17 @@
import { Config as GeneratedTypes } from 'payload/generated-types';
import { Document } from '../../../types';
import { Config as GeneratedTypes } from '../../../generated-types';
import { Document, Where } from '../../../types';
import { PayloadRequest } from '../../../express/types';
import { Payload } from '../../../payload';
import deleteOperation from '../delete';
import deleteByID from '../deleteByID';
import { getDataLoader } from '../../dataloader';
import i18n from '../../../translations/init';
import { APIError } from '../../../errors';
import { BulkOperationResult } from '../../config/types';
export type Options<T extends keyof GeneratedTypes['collections']> = {
export type BaseOptions<T extends keyof GeneratedTypes['collections']> = {
collection: T
id: string
id: string | number
depth?: number
locale?: string
fallbackLocale?: string
@@ -18,14 +20,26 @@ export type Options<T extends keyof GeneratedTypes['collections']> = {
showHiddenFields?: boolean
}
export default async function deleteLocal<TSlug extends keyof GeneratedTypes['collections']>(
payload: Payload,
options: Options<TSlug>,
): Promise<GeneratedTypes['collections'][TSlug]> {
export type ByIDOptions<T extends keyof GeneratedTypes['collections']> = BaseOptions<T> & {
where?: never
}
export type ManyOptions<T extends keyof GeneratedTypes['collections']> = BaseOptions<T> & {
where: Where
id?: never
}
export type Options<TSlug extends keyof GeneratedTypes['collections']> = ByIDOptions<TSlug> | ManyOptions<TSlug>
async function deleteLocal<TSlug extends keyof GeneratedTypes['collections']>(payload: Payload, options: ByIDOptions<TSlug>): Promise<GeneratedTypes['collections'][TSlug]>
async function deleteLocal<TSlug extends keyof GeneratedTypes['collections']>(payload: Payload, options: ManyOptions<TSlug>): Promise<BulkOperationResult<TSlug>>
async function deleteLocal<TSlug extends keyof GeneratedTypes['collections']>(payload: Payload, options: Options<TSlug>): Promise<GeneratedTypes['collections'][TSlug] | BulkOperationResult<TSlug>>
async function deleteLocal<TSlug extends keyof GeneratedTypes['collections']>(payload: Payload, options: Options<TSlug>): Promise<GeneratedTypes['collections'][TSlug] | BulkOperationResult<TSlug>> {
const {
collection: collectionSlug,
depth,
id,
where,
locale = null,
fallbackLocale = null,
user,
@@ -53,12 +67,20 @@ export default async function deleteLocal<TSlug extends keyof GeneratedTypes['co
if (!req.t) req.t = req.i18n.t;
if (!req.payloadDataLoader) req.payloadDataLoader = getDataLoader(req);
return deleteOperation<TSlug>({
const args = {
depth,
id,
where,
collection,
overrideAccess,
showHiddenFields,
req,
});
};
if (options.id) {
return deleteByID<TSlug>(args);
}
return deleteOperation<TSlug>(args);
}
export default deleteLocal;

View File

@@ -1,18 +1,32 @@
import { Config as GeneratedTypes } from 'payload/generated-types';
import find from './find';
import findByID from './findByID';
import create from './create';
import update from './update';
import localDelete from './delete';
import update, { ByIDOptions as UpdateByIDOptions, ManyOptions as UpdateManyOptions, Options as UpdateOptions } from './update';
import deleteLocal, { ByIDOptions as DeleteByIDOptions, ManyOptions as DeleteManyOptions, Options as DeleteOptions } from './delete';
import auth from '../../../auth/operations/local';
import findVersionByID from './findVersionByID';
import findVersions from './findVersions';
import restoreVersion from './restoreVersion';
import { BulkOperationResult } from '../../config/types';
async function localUpdate <T extends keyof GeneratedTypes['collections']>(options: UpdateByIDOptions<T>): Promise<GeneratedTypes['collections'][T]>
async function localUpdate <T extends keyof GeneratedTypes['collections']>(options: UpdateManyOptions<T>): Promise<BulkOperationResult<T>>
async function localUpdate <T extends keyof GeneratedTypes['collections']>(options: UpdateOptions<T>): Promise<GeneratedTypes['collections'][T] | BulkOperationResult<T>> {
return update<T>(this, options);
}
async function localDelete <T extends keyof GeneratedTypes['collections']>(options: DeleteByIDOptions<T>): Promise<GeneratedTypes['collections'][T]>
async function localDelete <T extends keyof GeneratedTypes['collections']>(options: DeleteManyOptions<T>): Promise<BulkOperationResult<T>>
async function localDelete <T extends keyof GeneratedTypes['collections']>(options: DeleteOptions<T>): Promise<GeneratedTypes['collections'][T] | BulkOperationResult<T>> {
return deleteLocal<T>(this, options);
}
export default {
find,
findByID,
create,
update,
update: localUpdate,
localDelete,
auth,
findVersionByID,

View File

@@ -1,6 +1,6 @@
import { Config as GeneratedTypes } from 'payload/generated-types';
import { Payload } from '../../../payload';
import { Document } from '../../../types';
import { Document, Where } from '../../../types';
import getFileByPath from '../../../uploads/getFileByPath';
import update from '../update';
import { PayloadRequest } from '../../../express/types';
@@ -8,10 +8,11 @@ import { getDataLoader } from '../../dataloader';
import { File } from '../../../uploads/types';
import i18nInit from '../../../translations/init';
import { APIError } from '../../../errors';
import updateByID from '../updateByID';
import { BulkOperationResult } from '../../config/types';
export type Options<TSlug extends keyof GeneratedTypes['collections']> = {
export type BaseOptions<TSlug extends keyof GeneratedTypes['collections']> = {
collection: TSlug
id: string | number
data: Partial<GeneratedTypes['collections'][TSlug]>
depth?: number
locale?: string
@@ -26,17 +27,28 @@ export type Options<TSlug extends keyof GeneratedTypes['collections']> = {
autosave?: boolean
}
export default async function updateLocal<TSlug extends keyof GeneratedTypes['collections']>(
payload: Payload,
options: Options<TSlug>,
): Promise<GeneratedTypes['collections'][TSlug]> {
export type ByIDOptions<TSlug extends keyof GeneratedTypes['collections']> = BaseOptions<TSlug> & {
id: string | number
where?: never
}
export type ManyOptions<TSlug extends keyof GeneratedTypes['collections']> = BaseOptions<TSlug> & {
where: Where
id?: never
}
export type Options<TSlug extends keyof GeneratedTypes['collections']> = ByIDOptions<TSlug> | ManyOptions<TSlug>
async function updateLocal<TSlug extends keyof GeneratedTypes['collections']>(payload: Payload, options: ByIDOptions<TSlug>): Promise<GeneratedTypes['collections'][TSlug]>
async function updateLocal<TSlug extends keyof GeneratedTypes['collections']>(payload: Payload, options: ManyOptions<TSlug>): Promise<BulkOperationResult<TSlug>>
async function updateLocal<TSlug extends keyof GeneratedTypes['collections']>(payload: Payload, options: Options<TSlug>): Promise<GeneratedTypes['collections'][TSlug] | BulkOperationResult<TSlug>>
async function updateLocal<TSlug extends keyof GeneratedTypes['collections']>(payload: Payload, options: Options<TSlug>): Promise<GeneratedTypes['collections'][TSlug] | BulkOperationResult<TSlug>> {
const {
collection: collectionSlug,
depth,
locale = null,
fallbackLocale = null,
data,
id,
user,
overrideAccess = true,
showHiddenFields,
@@ -45,6 +57,8 @@ export default async function updateLocal<TSlug extends keyof GeneratedTypes['co
overwriteExistingFiles = false,
draft,
autosave,
id,
where,
} = options;
const collection = payload.collections[collectionSlug];
@@ -76,14 +90,20 @@ export default async function updateLocal<TSlug extends keyof GeneratedTypes['co
data,
collection,
overrideAccess,
id,
showHiddenFields,
overwriteExistingFiles,
draft,
autosave,
payload,
req,
id,
where,
};
if (options.id) {
return updateByID<TSlug>(args);
}
return update<TSlug>(args);
}
export default updateLocal;

View File

@@ -1,13 +1,10 @@
import fs from 'fs';
import { promisify } from 'util';
import path from 'path';
import httpStatus from 'http-status';
import { Config as GeneratedTypes } from 'payload/generated-types';
import { Where, Document } from '../../types';
import { Collection } from '../config/types';
import { Document, Where } from '../../types';
import { BulkOperationResult, Collection } from '../config/types';
import sanitizeInternalFields from '../../utilities/sanitizeInternalFields';
import executeAccess from '../../auth/executeAccess';
import { NotFound, Forbidden, APIError, ValidationError, ErrorDeletingFile } from '../../errors';
import { APIError, ValidationError } from '../../errors';
import { PayloadRequest } from '../../express/types';
import { hasWhereAccessResult } from '../../auth/types';
import { saveVersion } from '../../versions/saveVersion';
@@ -17,17 +14,15 @@ import { beforeValidate } from '../../fields/hooks/beforeValidate';
import { afterChange } from '../../fields/hooks/afterChange';
import { afterRead } from '../../fields/hooks/afterRead';
import { generateFileData } from '../../uploads/generateFileData';
import { getLatestCollectionVersion } from '../../versions/getLatestCollectionVersion';
import { mapAsync } from '../../utilities/mapAsync';
import fileExists from '../../uploads/fileExists';
import { FileData } from '../../uploads/types';
const unlinkFile = promisify(fs.unlink);
import { AccessResult } from '../../config/types';
import { queryDrafts } from '../../versions/drafts/queryDrafts';
import { deleteAssociatedFiles } from '../../uploads/deleteAssociatedFiles';
import { unlinkTempFiles } from '../../uploads/unlinkTempFiles';
export type Arguments<T extends { [field: string | number | symbol]: unknown }> = {
collection: Collection
req: PayloadRequest
id: string | number
where: Where
data: Partial<T>
depth?: number
disableVerificationEmail?: boolean
@@ -35,12 +30,10 @@ export type Arguments<T extends { [field: string | number | symbol]: unknown }>
showHiddenFields?: boolean
overwriteExistingFiles?: boolean
draft?: boolean
autosave?: boolean
}
async function update<TSlug extends keyof GeneratedTypes['collections']>(
incomingArgs: Arguments<GeneratedTypes['collections'][TSlug]>,
): Promise<GeneratedTypes['collections'][TSlug]> {
): Promise<BulkOperationResult<TSlug>> {
let args = incomingArgs;
// /////////////////////////////////////
@@ -63,7 +56,7 @@ async function update<TSlug extends keyof GeneratedTypes['collections']>(
Model,
config: collectionConfig,
},
id,
where,
req,
req: {
t,
@@ -77,77 +70,76 @@ async function update<TSlug extends keyof GeneratedTypes['collections']>(
showHiddenFields,
overwriteExistingFiles = false,
draft: draftArg = false,
autosave = false,
} = args;
if (!id) {
throw new APIError('Missing ID of document to update.', httpStatus.BAD_REQUEST);
if (!where) {
throw new APIError('Missing \'where\' query of documents to update.', httpStatus.BAD_REQUEST);
}
let { data } = args;
const { password } = data;
const shouldSaveDraft = Boolean(draftArg && collectionConfig.versions.drafts);
const shouldSavePassword = Boolean(password && collectionConfig.auth && !shouldSaveDraft);
const lean = !shouldSavePassword;
// /////////////////////////////////////
// Access
// /////////////////////////////////////
const accessResults = !overrideAccess ? await executeAccess({ req, id, data }, collectionConfig.access.update) : true;
const hasWherePolicy = hasWhereAccessResult(accessResults);
// /////////////////////////////////////
// Retrieve document
// /////////////////////////////////////
const queryToBuild: { where: Where } = {
const queryToBuild: { where?: Where } = {
where: {
and: [
{
id: {
equals: id,
},
},
],
and: [],
},
};
if (hasWhereAccessResult(accessResults)) {
(queryToBuild.where.and as Where[]).push(accessResults);
if (where) {
queryToBuild.where = {
and: [],
...where,
};
if (Array.isArray(where.AND)) {
queryToBuild.where.and = [
...queryToBuild.where.and,
...where.AND,
];
}
}
let accessResult: AccessResult;
if (!overrideAccess) {
accessResult = await executeAccess({ req }, collectionConfig.access.update);
if (hasWhereAccessResult(accessResult)) {
queryToBuild.where.and.push(accessResult);
}
}
const query = await Model.buildQuery(queryToBuild, locale);
const doc = await getLatestCollectionVersion({
payload,
Model,
config: collectionConfig,
id,
query,
lean,
});
// /////////////////////////////////////
// Retrieve documents
// /////////////////////////////////////
let docs;
if (!doc && !hasWherePolicy) throw new NotFound(t);
if (!doc && hasWherePolicy) throw new Forbidden(t);
let docWithLocales: Document = JSON.stringify(lean ? doc : doc.toJSON({ virtuals: true }));
docWithLocales = JSON.parse(docWithLocales);
const originalDoc = await afterRead({
depth: 0,
doc: docWithLocales,
entityConfig: collectionConfig,
req,
overrideAccess: true,
showHiddenFields: true,
});
if (collectionConfig.versions?.drafts && shouldSaveDraft) {
docs = await queryDrafts<GeneratedTypes['collections'][TSlug]>({
accessResult,
collection,
locale,
payload,
where: query,
});
} else {
docs = await Model.find(query, {}, { lean: true });
}
// /////////////////////////////////////
// Generate data for all files and sizes
// /////////////////////////////////////
const { data: newFileData, files: filesToUpload } = await generateFileData({
const {
data: newFileData,
files: filesToUpload,
} = await generateFileData({
config,
collection,
req,
@@ -158,229 +150,217 @@ async function update<TSlug extends keyof GeneratedTypes['collections']>(
data = newFileData;
// /////////////////////////////////////
// beforeValidate - Fields
// /////////////////////////////////////
const errors = [];
data = await beforeValidate<GeneratedTypes['collections'][TSlug]>({
data,
doc: originalDoc,
entityConfig: collectionConfig,
id,
operation: 'update',
overrideAccess,
req,
});
const promises = docs.map(async (doc) => {
let docWithLocales: Document = JSON.stringify(doc);
docWithLocales = JSON.parse(docWithLocales);
// /////////////////////////////////////
// beforeValidate - Collection
// /////////////////////////////////////
const id = docWithLocales._id;
await collectionConfig.hooks.beforeValidate.reduce(async (priorHook, hook) => {
await priorHook;
data = (await hook({
data,
req,
operation: 'update',
originalDoc,
})) || data;
}, Promise.resolve());
// /////////////////////////////////////
// Write files to local storage
// /////////////////////////////////////
if (!collectionConfig.upload.disableLocalStorage) {
await uploadFiles(payload, filesToUpload, t);
}
// /////////////////////////////////////
// beforeChange - Collection
// /////////////////////////////////////
await collectionConfig.hooks.beforeChange.reduce(async (priorHook, hook) => {
await priorHook;
data = (await hook({
data,
req,
originalDoc,
operation: 'update',
})) || data;
}, Promise.resolve());
// /////////////////////////////////////
// beforeChange - Fields
// /////////////////////////////////////
let result = await beforeChange<GeneratedTypes['collections'][TSlug]>({
data,
doc: originalDoc,
docWithLocales,
entityConfig: collectionConfig,
id,
operation: 'update',
req,
skipValidation: shouldSaveDraft || data._status === 'draft',
});
// /////////////////////////////////////
// Handle potential password update
// /////////////////////////////////////
if (shouldSavePassword) {
await doc.setPassword(password);
await doc.save();
delete data.password;
delete result.password;
}
// /////////////////////////////////////
// Update
// /////////////////////////////////////
if (!shouldSaveDraft) {
try {
result = await Model.findByIdAndUpdate(
{ _id: id },
result,
{ new: true },
);
} catch (error) {
// Handle uniqueness error from MongoDB
throw error.code === 11000 && error.keyValue
? new ValidationError([{ message: 'Value must be unique', field: Object.keys(error.keyValue)[0] }], t)
: error;
}
}
result = JSON.parse(JSON.stringify(result));
result.id = result._id as string | number;
result = sanitizeInternalFields(result);
// /////////////////////////////////////
// Delete any associated files
// /////////////////////////////////////
if (collectionConfig.upload && !overwriteExistingFiles && filesToUpload && filesToUpload.length > 0) {
const { staticDir } = collectionConfig.upload;
const staticPath = path.resolve(config.paths.configDir, staticDir);
const fileToDelete = `${staticPath}/${doc.filename}`;
if (await fileExists(fileToDelete)) {
fs.unlink(fileToDelete, (err) => {
if (err) {
throw new ErrorDeletingFile(t);
}
const originalDoc = await afterRead({
depth: 0,
doc: docWithLocales,
entityConfig: collectionConfig,
req,
overrideAccess: true,
showHiddenFields: true,
});
}
if (doc.sizes) {
Object.values(doc.sizes).forEach(async (size: FileData) => {
const sizeToDelete = `${staticPath}/${size.filename}`;
if (await fileExists(sizeToDelete)) {
fs.unlink(sizeToDelete, (err) => {
if (err) {
throw new ErrorDeletingFile(t);
}
});
}
await deleteAssociatedFiles({ config, collectionConfig, files: filesToUpload, doc: docWithLocales, t, overrideDelete: false });
// /////////////////////////////////////
// beforeValidate - Fields
// /////////////////////////////////////
data = await beforeValidate<GeneratedTypes['collections'][TSlug]>({
data,
doc: originalDoc,
entityConfig: collectionConfig,
id,
operation: 'update',
overrideAccess,
req,
});
}
}
// /////////////////////////////////////
// Create version
// /////////////////////////////////////
// /////////////////////////////////////
// beforeValidate - Collection
// /////////////////////////////////////
if (collectionConfig.versions) {
result = await saveVersion({
payload,
collection: collectionConfig,
req,
docWithLocales: {
...result,
createdAt: docWithLocales.createdAt,
},
id,
autosave,
draft: shouldSaveDraft,
});
}
await collectionConfig.hooks.beforeValidate.reduce(async (priorHook, hook) => {
await priorHook;
// /////////////////////////////////////
// afterRead - Fields
// /////////////////////////////////////
data = (await hook({
data,
req,
operation: 'update',
originalDoc,
})) || data;
}, Promise.resolve());
result = await afterRead({
depth,
doc: result,
entityConfig: collectionConfig,
req,
overrideAccess,
showHiddenFields,
});
// /////////////////////////////////////
// Write files to local storage
// /////////////////////////////////////
// /////////////////////////////////////
// afterRead - Collection
// /////////////////////////////////////
await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => {
await priorHook;
result = await hook({
req,
doc: result,
}) || result;
}, Promise.resolve());
// /////////////////////////////////////
// afterChange - Fields
// /////////////////////////////////////
result = await afterChange<GeneratedTypes['collections'][TSlug]>({
data,
doc: result,
previousDoc: originalDoc,
entityConfig: collectionConfig,
operation: 'update',
req,
});
// /////////////////////////////////////
// afterChange - Collection
// /////////////////////////////////////
await collectionConfig.hooks.afterChange.reduce(async (priorHook, hook) => {
await priorHook;
result = await hook({
doc: result,
previousDoc: originalDoc,
req,
operation: 'update',
}) || result;
}, Promise.resolve());
// Remove temp files if enabled, as express-fileupload does not do this automatically
if (config.upload?.useTempFiles && collectionConfig.upload) {
const { files } = req;
const fileArray = Array.isArray(files) ? files : [files];
await mapAsync(fileArray, async ({ file }) => {
// Still need this check because this will not be populated if using local API
if (file.tempFilePath) {
await unlinkFile(file.tempFilePath);
if (!collectionConfig.upload.disableLocalStorage) {
await uploadFiles(payload, filesToUpload, t);
}
});
}
// /////////////////////////////////////
// Return results
// /////////////////////////////////////
return result;
// /////////////////////////////////////
// beforeChange - Collection
// /////////////////////////////////////
await collectionConfig.hooks.beforeChange.reduce(async (priorHook, hook) => {
await priorHook;
data = (await hook({
data,
req,
originalDoc,
operation: 'update',
})) || data;
}, Promise.resolve());
// /////////////////////////////////////
// beforeChange - Fields
// /////////////////////////////////////
let result = await beforeChange<GeneratedTypes['collections'][TSlug]>({
data,
doc: originalDoc,
docWithLocales,
entityConfig: collectionConfig,
id,
operation: 'update',
req,
skipValidation: shouldSaveDraft || data._status === 'draft',
});
// /////////////////////////////////////
// Update
// /////////////////////////////////////
if (!shouldSaveDraft) {
try {
result = await Model.findByIdAndUpdate(
{ _id: id },
result,
{ new: true },
);
} catch (error) {
// Handle uniqueness error from MongoDB
throw error.code === 11000 && error.keyValue
? new ValidationError([{
message: 'Value must be unique',
field: Object.keys(error.keyValue)[0],
}], t)
: error;
}
}
result = JSON.parse(JSON.stringify(result));
result.id = result._id as string | number;
result = sanitizeInternalFields(result);
// /////////////////////////////////////
// Create version
// /////////////////////////////////////
if (collectionConfig.versions) {
result = await saveVersion({
payload,
collection: collectionConfig,
req,
docWithLocales: {
...result,
createdAt: docWithLocales.createdAt,
},
id,
draft: shouldSaveDraft,
});
}
// /////////////////////////////////////
// afterRead - Fields
// /////////////////////////////////////
result = await afterRead({
depth,
doc: result,
entityConfig: collectionConfig,
req,
overrideAccess,
showHiddenFields,
});
// /////////////////////////////////////
// afterRead - Collection
// /////////////////////////////////////
await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => {
await priorHook;
result = await hook({
req,
doc: result,
}) || result;
}, Promise.resolve());
// /////////////////////////////////////
// afterChange - Fields
// /////////////////////////////////////
result = await afterChange<GeneratedTypes['collections'][TSlug]>({
data,
doc: result,
previousDoc: originalDoc,
entityConfig: collectionConfig,
operation: 'update',
req,
});
// /////////////////////////////////////
// afterChange - Collection
// /////////////////////////////////////
await collectionConfig.hooks.afterChange.reduce(async (priorHook, hook) => {
await priorHook;
result = await hook({
doc: result,
previousDoc: originalDoc,
req,
operation: 'update',
}) || result;
}, Promise.resolve());
await unlinkTempFiles({
req,
config,
collectionConfig,
});
// /////////////////////////////////////
// Return results
// /////////////////////////////////////
return result;
} catch (error) {
errors.push({
message: error.message,
id,
});
}
return null;
});
const awaitedDocs = await Promise.all(promises);
return {
docs: awaitedDocs.filter(Boolean),
errors,
};
}
export default update;

View File

@@ -0,0 +1,348 @@
import httpStatus from 'http-status';
import { Config as GeneratedTypes } from 'payload/generated-types';
import { Where, Document } from '../../types';
import { Collection } from '../config/types';
import sanitizeInternalFields from '../../utilities/sanitizeInternalFields';
import executeAccess from '../../auth/executeAccess';
import { NotFound, Forbidden, APIError, ValidationError } from '../../errors';
import { PayloadRequest } from '../../express/types';
import { hasWhereAccessResult } from '../../auth/types';
import { saveVersion } from '../../versions/saveVersion';
import { uploadFiles } from '../../uploads/uploadFiles';
import { beforeChange } from '../../fields/hooks/beforeChange';
import { beforeValidate } from '../../fields/hooks/beforeValidate';
import { afterChange } from '../../fields/hooks/afterChange';
import { afterRead } from '../../fields/hooks/afterRead';
import { generateFileData } from '../../uploads/generateFileData';
import { getLatestCollectionVersion } from '../../versions/getLatestCollectionVersion';
import { deleteAssociatedFiles } from '../../uploads/deleteAssociatedFiles';
import { unlinkTempFiles } from '../../uploads/unlinkTempFiles';
export type Arguments<T extends { [field: string | number | symbol]: unknown }> = {
collection: Collection
req: PayloadRequest
id: string | number
data: Partial<T>
depth?: number
disableVerificationEmail?: boolean
overrideAccess?: boolean
showHiddenFields?: boolean
overwriteExistingFiles?: boolean
draft?: boolean
autosave?: boolean
}
async function updateByID<TSlug extends keyof GeneratedTypes['collections']>(
incomingArgs: Arguments<GeneratedTypes['collections'][TSlug]>,
): Promise<GeneratedTypes['collections'][TSlug]> {
let args = incomingArgs;
// /////////////////////////////////////
// beforeOperation - Collection
// /////////////////////////////////////
await args.collection.config.hooks.beforeOperation.reduce(async (priorHook, hook) => {
await priorHook;
args = (await hook({
args,
operation: 'update',
})) || args;
}, Promise.resolve());
const {
depth,
collection,
collection: {
Model,
config: collectionConfig,
},
id,
req,
req: {
t,
locale,
payload,
payload: {
config,
},
},
overrideAccess,
showHiddenFields,
overwriteExistingFiles = false,
draft: draftArg = false,
autosave = false,
} = args;
if (!id) {
throw new APIError('Missing ID of document to update.', httpStatus.BAD_REQUEST);
}
let { data } = args;
const { password } = data;
const shouldSaveDraft = Boolean(draftArg && collectionConfig.versions.drafts);
const shouldSavePassword = Boolean(password && collectionConfig.auth && !shouldSaveDraft);
const lean = !shouldSavePassword;
// /////////////////////////////////////
// Access
// /////////////////////////////////////
const accessResults = !overrideAccess ? await executeAccess({ req, id, data }, collectionConfig.access.update) : true;
const hasWherePolicy = hasWhereAccessResult(accessResults);
// /////////////////////////////////////
// Retrieve document
// /////////////////////////////////////
const queryToBuild: { where: Where } = {
where: {
and: [
{
id: {
equals: id,
},
},
],
},
};
if (hasWhereAccessResult(accessResults)) {
(queryToBuild.where.and as Where[]).push(accessResults);
}
const query = await Model.buildQuery(queryToBuild, locale);
const doc = await getLatestCollectionVersion({
payload,
Model,
config: collectionConfig,
id,
query,
lean,
});
if (!doc && !hasWherePolicy) throw new NotFound(t);
if (!doc && hasWherePolicy) throw new Forbidden(t);
let docWithLocales: Document = JSON.stringify(lean ? doc : doc.toJSON({ virtuals: true }));
docWithLocales = JSON.parse(docWithLocales);
const originalDoc = await afterRead({
depth: 0,
doc: docWithLocales,
entityConfig: collectionConfig,
req,
overrideAccess: true,
showHiddenFields: true,
});
// /////////////////////////////////////
// Generate data for all files and sizes
// /////////////////////////////////////
const { data: newFileData, files: filesToUpload } = await generateFileData({
config,
collection,
req,
data,
throwOnMissingFile: false,
overwriteExistingFiles,
});
data = newFileData;
// /////////////////////////////////////
// Delete any associated files
// /////////////////////////////////////
await deleteAssociatedFiles({ config, collectionConfig, files: filesToUpload, doc, t, overrideDelete: false });
// /////////////////////////////////////
// beforeValidate - Fields
// /////////////////////////////////////
data = await beforeValidate<GeneratedTypes['collections'][TSlug]>({
data,
doc: originalDoc,
entityConfig: collectionConfig,
id,
operation: 'update',
overrideAccess,
req,
});
// /////////////////////////////////////
// beforeValidate - Collection
// /////////////////////////////////////
await collectionConfig.hooks.beforeValidate.reduce(async (priorHook, hook) => {
await priorHook;
data = (await hook({
data,
req,
operation: 'update',
originalDoc,
})) || data;
}, Promise.resolve());
// /////////////////////////////////////
// Write files to local storage
// /////////////////////////////////////
if (!collectionConfig.upload.disableLocalStorage) {
await uploadFiles(payload, filesToUpload, t);
}
// /////////////////////////////////////
// beforeChange - Collection
// /////////////////////////////////////
await collectionConfig.hooks.beforeChange.reduce(async (priorHook, hook) => {
await priorHook;
data = (await hook({
data,
req,
originalDoc,
operation: 'update',
})) || data;
}, Promise.resolve());
// /////////////////////////////////////
// beforeChange - Fields
// /////////////////////////////////////
let result = await beforeChange<GeneratedTypes['collections'][TSlug]>({
data,
doc: originalDoc,
docWithLocales,
entityConfig: collectionConfig,
id,
operation: 'update',
req,
skipValidation: shouldSaveDraft || data._status === 'draft',
});
// /////////////////////////////////////
// Handle potential password update
// /////////////////////////////////////
if (shouldSavePassword) {
await doc.setPassword(password);
await doc.save();
delete data.password;
delete result.password;
}
// /////////////////////////////////////
// Update
// /////////////////////////////////////
if (!shouldSaveDraft) {
try {
result = await Model.findByIdAndUpdate(
{ _id: id },
result,
{ new: true },
);
} catch (error) {
// Handle uniqueness error from MongoDB
throw error.code === 11000 && error.keyValue
? new ValidationError([{ message: 'Value must be unique', field: Object.keys(error.keyValue)[0] }], t)
: error;
}
}
result = JSON.parse(JSON.stringify(result));
result.id = result._id as string | number;
result = sanitizeInternalFields(result);
// /////////////////////////////////////
// Create version
// /////////////////////////////////////
if (collectionConfig.versions) {
result = await saveVersion({
payload,
collection: collectionConfig,
req,
docWithLocales: {
...result,
createdAt: docWithLocales.createdAt,
},
id,
autosave,
draft: shouldSaveDraft,
});
}
// /////////////////////////////////////
// afterRead - Fields
// /////////////////////////////////////
result = await afterRead({
depth,
doc: result,
entityConfig: collectionConfig,
req,
overrideAccess,
showHiddenFields,
});
// /////////////////////////////////////
// afterRead - Collection
// /////////////////////////////////////
await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => {
await priorHook;
result = await hook({
req,
doc: result,
}) || result;
}, Promise.resolve());
// /////////////////////////////////////
// afterChange - Fields
// /////////////////////////////////////
result = await afterChange<GeneratedTypes['collections'][TSlug]>({
data,
doc: result,
previousDoc: originalDoc,
entityConfig: collectionConfig,
operation: 'update',
req,
});
// /////////////////////////////////////
// afterChange - Collection
// /////////////////////////////////////
await collectionConfig.hooks.afterChange.reduce(async (priorHook, hook) => {
await priorHook;
result = await hook({
doc: result,
previousDoc: originalDoc,
req,
operation: 'update',
}) || result;
}, Promise.resolve());
await unlinkTempFiles({
req,
config,
collectionConfig,
});
// /////////////////////////////////////
// Return results
// /////////////////////////////////////
return result;
}
export default updateByID;

View File

@@ -1,9 +1,10 @@
import { Response, NextFunction } from 'express';
import httpStatus from 'http-status';
import { PayloadRequest } from '../../express/types';
import { NotFound } from '../../errors';
import { Document } from '../../types';
import { Document, Where } from '../../types';
import deleteOperation from '../operations/delete';
import formatSuccessResponse from '../../express/responses/formatSuccess';
import { getTranslation } from '../../utilities/getTranslation';
export type DeleteResult = {
message: string;
@@ -12,18 +13,36 @@ export type DeleteResult = {
export default async function deleteHandler(req: PayloadRequest, res: Response, next: NextFunction): Promise<Response<DeleteResult> | void> {
try {
const doc = await deleteOperation({
const result = await deleteOperation({
req,
collection: req.collection,
id: req.params.id,
where: req.query.where as Where,
depth: parseInt(String(req.query.depth), 10),
});
if (!doc) {
return res.status(httpStatus.NOT_FOUND).json(new NotFound(req.t));
if (result.errors.length === 0) {
const message = req.t('general:deletedCountSuccessfully', {
count: result.docs.length,
label: getTranslation(req.collection.config.labels[result.docs.length > 1 ? 'plural' : 'singular'], req.i18n),
});
return res.status(httpStatus.OK).json({
...formatSuccessResponse(message, 'message'),
...result,
});
}
return res.status(httpStatus.OK).send(doc);
const total = result.docs.length + result.errors.length;
const message = req.t('error:unableToDeleteCount', {
count: result.errors.length,
total,
label: getTranslation(req.collection.config.labels[total > 1 ? 'plural' : 'singular'], req.i18n),
});
return res.status(httpStatus.BAD_REQUEST).json({
message,
...result,
});
} catch (error) {
return next(error);
}

View File

@@ -0,0 +1,30 @@
import { Response, NextFunction } from 'express';
import httpStatus from 'http-status';
import { PayloadRequest } from '../../express/types';
import { NotFound } from '../../errors';
import { Document } from '../../types';
import deleteByID from '../operations/deleteByID';
export type DeleteResult = {
message: string;
doc: Document;
}
export default async function deleteByIDHandler(req: PayloadRequest, res: Response, next: NextFunction): Promise<Response<DeleteResult> | void> {
try {
const doc = await deleteByID({
req,
collection: req.collection,
id: req.params.id,
depth: parseInt(String(req.query.depth), 10),
});
if (!doc) {
return res.status(httpStatus.NOT_FOUND).json(new NotFound(req.t));
}
return res.status(httpStatus.OK).send(doc);
} catch (error) {
return next(error);
}
}

View File

@@ -1,44 +1,51 @@
import { Response, NextFunction } from 'express';
import httpStatus from 'http-status';
import { Where, Document } from '../../types';
import { PayloadRequest } from '../../express/types';
import formatSuccessResponse from '../../express/responses/formatSuccess';
import { Document } from '../../types';
import update from '../operations/update';
import { getTranslation } from '../../utilities/getTranslation';
export type UpdateResult = {
message: string
doc: Document
};
export async function deprecatedUpdate(req: PayloadRequest, res: Response, next: NextFunction): Promise<Response<UpdateResult> | void> {
req.payload.logger.warn('The PUT method is deprecated and will no longer be supported in a future release. Please use the PATCH method for update requests.');
return updateHandler(req, res, next);
}
export default async function updateHandler(req: PayloadRequest, res: Response, next: NextFunction): Promise<Response<UpdateResult> | void> {
try {
const draft = req.query.draft === 'true';
const autosave = req.query.autosave === 'true';
const doc = await update({
const result = await update({
req,
collection: req.collection,
id: req.params.id,
where: req.query.where as Where,
data: req.body,
depth: parseInt(String(req.query.depth), 10),
draft,
autosave,
});
let message = req.t('general:updatedSuccessfully');
if (result.errors.length === 0) {
const message = req.t('general:updatedCountSuccessfully', {
count: result.docs.length,
label: getTranslation(req.collection.config.labels[result.docs.length > 1 ? 'plural' : 'singular'], req.i18n),
});
if (draft) message = req.t('version:draftSavedSuccessfully');
if (autosave) message = req.t('version:autosavedSuccessfully');
return res.status(httpStatus.OK).json({
...formatSuccessResponse(message, 'message'),
...result,
});
}
return res.status(httpStatus.OK).json({
const total = result.docs.length + result.errors.length;
const message = req.t('error:unableToUpdateCount', {
count: result.errors.length,
total,
label: getTranslation(req.collection.config.labels[total > 1 ? 'plural' : 'singular'], req.i18n),
});
return res.status(httpStatus.BAD_REQUEST).json({
...formatSuccessResponse(message, 'message'),
doc,
...result,
});
} catch (error) {
return next(error);

View File

@@ -0,0 +1,45 @@
import { Response, NextFunction } from 'express';
import httpStatus from 'http-status';
import { PayloadRequest } from '../../express/types';
import formatSuccessResponse from '../../express/responses/formatSuccess';
import updateByID from '../operations/updateByID';
export type UpdateResult = {
message: string
doc: Document
};
export async function deprecatedUpdate(req: PayloadRequest, res: Response, next: NextFunction): Promise<Response<UpdateResult> | void> {
req.payload.logger.warn('The PUT method is deprecated and will no longer be supported in a future release. Please use the PATCH method for update requests.');
return updateByIDHandler(req, res, next);
}
export default async function updateByIDHandler(req: PayloadRequest, res: Response, next: NextFunction): Promise<Response<UpdateResult> | void> {
try {
const draft = req.query.draft === 'true';
const autosave = req.query.autosave === 'true';
const doc = await updateByID({
req,
collection: req.collection,
id: req.params.id,
data: req.body,
depth: parseInt(String(req.query.depth), 10),
draft,
autosave,
});
let message = req.t('general:updatedSuccessfully');
if (draft) message = req.t('version:draftSavedSuccessfully');
if (autosave) message = req.t('version:autosavedSuccessfully');
return res.status(httpStatus.OK).json({
...formatSuccessResponse(message, 'message'),
doc,
});
} catch (error) {
return next(error);
}
}

View File

@@ -21,6 +21,7 @@ export const baseAdminFields = joi.object().keys({
initCollapsed: joi.boolean().default(false),
hidden: joi.boolean().default(false),
disabled: joi.boolean().default(false),
disableBulkEdit: joi.boolean().default(false),
condition: joi.func(),
components: baseAdminComponentFields,
});

View File

@@ -70,6 +70,7 @@ type Admin = {
Cell?: React.ComponentType<any>;
Field?: React.ComponentType<any>;
}
disableBulkEdit?: boolean
hidden?: boolean
}
@@ -232,6 +233,7 @@ export type UIField = {
position?: string
width?: string
condition?: Condition
disableBulkEdit?: boolean
components?: {
Filter?: React.ComponentType<any>;
Cell?: React.ComponentType<any>;

View File

@@ -65,7 +65,7 @@ export const promise = async ({
fields: field.fields,
operation,
req,
siblingData: siblingData[field.name] as Record<string, unknown> || {},
siblingData: siblingData?.[field.name] as Record<string, unknown> || {},
siblingDoc: siblingDoc[field.name] as Record<string, unknown>,
});
@@ -82,11 +82,11 @@ export const promise = async ({
data,
doc,
previousDoc,
previousSiblingDoc: previousDoc[field.name]?.[i] || {} as Record<string, unknown>,
previousSiblingDoc: previousDoc?.[field.name]?.[i] || {} as Record<string, unknown>,
fields: field.fields,
operation,
req,
siblingData: siblingData[field.name]?.[i] || {},
siblingData: siblingData?.[field.name]?.[i] || {},
siblingDoc: { ...row } || {},
}));
});
@@ -108,11 +108,11 @@ export const promise = async ({
data,
doc,
previousDoc,
previousSiblingDoc: previousDoc[field.name]?.[i] || {} as Record<string, unknown>,
previousSiblingDoc: previousDoc?.[field.name]?.[i] || {} as Record<string, unknown>,
fields: block.fields,
operation,
req,
siblingData: siblingData[field.name]?.[i] || {},
siblingData: siblingData?.[field.name]?.[i] || {},
siblingDoc: { ...row } || {},
}));
}

View File

@@ -1,7 +1,5 @@
import { Config as GeneratedTypes } from 'payload/generated-types';
import {
InitOptions,
} from './config/types';
import { InitOptions } from './config/types';
import { initHTTP } from './initHTTP';
import { Payload as LocalPayload, BasePayload } from './payload';

View File

@@ -29,8 +29,6 @@ import { Preferences } from './preferences/types';
import { Options as CreateOptions } from './collections/operations/local/create';
import { Options as FindOptions } from './collections/operations/local/find';
import { Options as FindByIDOptions } from './collections/operations/local/findByID';
import { Options as UpdateOptions } from './collections/operations/local/update';
import { Options as DeleteOptions } from './collections/operations/local/delete';
import { Options as FindVersionsOptions } from './collections/operations/local/findVersions';
import { Options as FindVersionByIDOptions } from './collections/operations/local/findVersionByID';
import { Options as RestoreVersionOptions } from './collections/operations/local/restoreVersion';
@@ -249,23 +247,18 @@ export class BasePayload<TGeneratedTypes extends GeneratedTypes> {
}
/**
* @description Update document
* @description Update one or more documents
* @param options
* @returns Updated document
* @returns Updated document(s)
*/
update = async <T extends keyof TGeneratedTypes['collections']>(
options: UpdateOptions<T>,
): Promise<TGeneratedTypes['collections'][T]> => {
const { update } = localOperations;
return update<T>(this, options);
}
update = localOperations.update
delete = async <T extends keyof TGeneratedTypes['collections']>(
options: DeleteOptions<T>,
): Promise<TGeneratedTypes['collections'][T]> => {
const { localDelete } = localOperations;
return localDelete<T>(this, options);
}
/**
* @description delete one or more documents
* @param options
* @returns Updated document(s)
*/
delete = localOperations.localDelete;
/**
* @description Find versions with criteria

View File

@@ -82,6 +82,8 @@
"problemUploadingFile": "Při nahrávání souboru došlo k chybě.",
"tokenInvalidOrExpired": "Token je neplatný nebo vypršel.",
"unPublishingDocument": "Při zrušení publikování tohoto dokumentu došlo k chybě.",
"unableToDeleteCount": "Nelze smazat {{count}} z {{total}} {{label}}",
"unableToUpdateCount": "Nelze aktualizovat {{count}} z {{total}} {{label}}.",
"unauthorized": "Neautorizováno, pro zadání tohoto požadavku musíte být přihlášeni.",
"unknown": "Došlo k neznámé chybě.",
"unspecific": "Došlo k chybě.",
@@ -124,6 +126,7 @@
"saveChanges": "Uložit změny",
"searchForBlock": "Hledat blok",
"selectExistingLabel": "Vybrat existující {{label}}",
"selectFieldsToEdit": "Vyberte pole, která chcete upravit",
"showAll": "Zobrazit vše",
"swapUpload": "Vyměnit nahrání",
"textToDisplay": "Text k zobrazení",
@@ -132,6 +135,9 @@
},
"general": {
"aboutToDelete": "Chystáte se odstranit {{label}} <1>{{title}}</1>. Jste si jisti?",
"aboutToDeleteCount_many": "Chystáte se smazat {{count}} {{label}}",
"aboutToDeleteCount_one": "Chystáte se smazat {{count}} {{label}}",
"aboutToDeleteCount_other": "Chystáte se smazat {{count}} {{label}}",
"addBelow": "Přidat pod",
"addFilter": "Přidat filtr",
"adminTheme": "Motiv administračního rozhraní",
@@ -159,6 +165,7 @@
"dark": "Tmavé",
"dashboard": "Nástěnka",
"delete": "Odstranit",
"deletedCountSuccessfully": "Úspěšně smazáno {{count}} {{label}}.",
"deletedSuccessfully": "Úspěšně odstraněno.",
"deleting": "Odstraňování...",
"descending": "Sestupně",
@@ -167,6 +174,9 @@
"edit": "Upravit",
"editLabel": "Upravit {{label}}",
"editing": "Úpravy",
"editingLabel_many": "Úprava {{count}} {{label}}",
"editingLabel_one": "Úprava {{count}} {{label}}",
"editingLabel_other": "Úprava {{count}} {{label}}",
"email": "E-mail",
"emailAddress": "E-mailová adresa",
"enterAValue": "Zadejte hodnotu",
@@ -205,7 +215,9 @@
"save": "Uložit",
"saving": "Ukládání...",
"searchBy": "Vyhledat podle {{label}}",
"selectAll": "Vybrat vše {{count}} {{label}}",
"selectValue": "Vyberte hodnotu",
"selectedCount": "Vybráno {{count}} {{label}}",
"sorryNotFound": "Je nám líto, ale neexistuje nic, co by odpovídalo vašemu požadavku.",
"sort": "Třídit",
"stayOnThisPage": "Zůstat na této stránce",
@@ -219,6 +231,7 @@
"unsavedChangesDuplicate": "Máte neuložené změny. Chtěli byste pokračovat v duplikování?",
"untitled": "Bez názvu",
"updatedAt": "Aktualizováno v",
"updatedCountSuccessfully": "Úspěšně aktualizováno {{count}} {{label}}.",
"updatedSuccessfully": "Úspěšně aktualizováno.",
"updating": "Aktualizace",
"uploading": "Nahrávání",
@@ -273,15 +286,18 @@
"validUploadID": "Toto pole není platné ID pro odeslání."
},
"version": {
"aboutToPublishSelection": "Chystáte se publikovat všechny {{label}} ve výběru. Jsi si jistá?",
"aboutToRestore": "Chystáte se obnovit tento {{label}} dokument do stavu, v jakém byl {{versionDate}}.",
"aboutToRestoreGlobal": "Chystáte se obnovit globální {{label}} do stavu, v jakém byl {{versionDate}}.",
"aboutToRevertToPublished": "Chystáte se vrátit změny tohoto dokumentu do jeho publikovaného stavu. Jste si jisti?",
"aboutToUnpublish": "Chystáte se zrušit publikování tohoto dokumentu. Jste si jisti?",
"aboutToUnpublishSelection": "Chystáte se zrušit publikování všech {{label}} ve výběru. Jsi si jistá?",
"autosave": "Automatické uložení",
"autosavedSuccessfully": "Úspěšně uloženo automaticky.",
"autosavedVersion": "Verze automatického uložení",
"changed": "Změněno",
"compareVersion": "Porovnat verzi s:",
"confirmPublish": "Potvrďte publikování",
"confirmRevertToSaved": "Potvrdit vrácení k uloženému",
"confirmUnpublish": "Potvrdit zrušení publikování",
"confirmVersionRestoration": "Potvrdit obnovení verze",
@@ -293,6 +309,7 @@
"noRowsFound": "Nenalezen {{label}}",
"preview": "Náhled",
"problemRestoringVersion": "Při obnovování této verze došlo k problému",
"publish": "Publikovat",
"publishChanges": "Publikovat změny",
"published": "Publikováno",
"restoreThisVersion": "Obnovit tuto verzi",
@@ -303,8 +320,8 @@
"saveDraft": "Uložit koncept",
"selectLocales": "Vyberte místní verze pro zobrazení",
"selectVersionToCompare": "Vyberte verzi pro porovnání",
"showingVersionsFor": "Zobrazují se verze pro:",
"showLocales": "Zobrazit místní verze:",
"showingVersionsFor": "Zobrazují se verze pro:",
"status": "Stav",
"type": "Typ",
"unpublish": "Zrušit publikování",

View File

@@ -60,6 +60,7 @@
"accountAlreadyActivated": "Dieses Konto wurde bereits aktiviert",
"autosaving": "Es gab ein Problem während der automatischen Speicherung für dieses Dokument",
"correctInvalidFields": "Bitte ungültige Felder korrigieren.",
"deletingFile": "Beim Löschen der Datei ist ein Fehler aufgetreten.",
"deletingTitle": "Es gab ein Problem während der Löschung von {{title}}. Bitte überprüfe deine Verbindung und versuche es erneut.",
"emailOrPasswordIncorrect": "Die E-Mail-Adresse oder das Passwort sind nicht korrekt.",
"followingFieldsInvalid_many": "Die folgenden Felder sind nicht korrekt:",
@@ -81,6 +82,8 @@
"problemUploadingFile": "Es gab ein Problem während des Hochladens der Datei.",
"tokenInvalidOrExpired": "Token ist entweder ungültig oder abgelaufen.",
"unPublishingDocument": "Es gab ein Problem, dieses Dokument auf Entwurf zu setzen.",
"unableToDeleteCount": "{{count}} von {{total}} {{label}} konnte nicht gelöscht werden.",
"unableToUpdateCount": "{{count}} von {{total}} {{label}} konnte nicht aktualisiert werden.",
"unauthorized": "Nicht autorisiert - du musst angemeldet sein, um diese Anfrage zu stellen.",
"unknown": "Ein unbekannter Fehler ist aufgetreten.",
"unspecific": "Ein Fehler ist aufgetreten.",
@@ -89,24 +92,24 @@
"verificationTokenInvalid": "Verifizierungs-Token ist nicht korrekt."
},
"fields": {
"block": "Block",
"blocks": "Blöcke",
"addLabel": "{{label}} hinzufügen",
"addLink": "Link Hinzufügen",
"addNew": "Neu erstellen",
"addNewLabel": "{{label}} erstellen",
"addRelationship": "Verknüpfung Hinzufügen",
"addUpload": "Hochladen Hinzufügen",
"block": "Block",
"blockType": "Block-Typ",
"blocks": "Blöcke",
"chooseBetweenCustomTextOrDocument": "Wähle zwischen einer eigenen Text-URL oder verlinke zu einem anderen Dokument.",
"chooseDocumentToLink": "Wähle ein Dokument zum Verlinken",
"chooseFromExisting": "Aus vorhandenen auswählen",
"chooseLabel": "{{label}} auswählen",
"collapseAll": "Alle einklappen",
"customURL": "Eigene URL",
"editLabelData": "{{label}} bearbeiten",
"editLink": "Bearbeite Link",
"editRelationship": "Beziehung Hinzufügen",
"editLabelData": "{{label}} bearbeiten",
"enterURL": "URL eingeben",
"internalLink": "Interner Link",
"itemsAndMore": "{{items}} und {{count}} mehr",
@@ -125,6 +128,7 @@
"saveChanges": "Änderungen speichern",
"searchForBlock": "Nach Block suchen",
"selectExistingLabel": "{{label}} auswählen (vorhandene)",
"selectFieldsToEdit": "Wählen Sie die zu bearbeitenden Felder aus",
"showAll": "Alle anzeigen",
"swapRelationship": "Beziehung Tauschen",
"swapUpload": "Datei Austauschen",
@@ -134,10 +138,14 @@
},
"general": {
"aboutToDelete": "Du bist dabei {{label}} <1>{{title}}</1> zu löschen. Bist du dir sicher?",
"aboutToDeleteCount_many": "Sie sind dabei, {{count}} {{label}} zu löschen",
"aboutToDeleteCount_one": "Sie sind dabei, {{count}} {{label}} zu löschen",
"aboutToDeleteCount_other": "Sie sind dabei, {{count}} {{label}} zu löschen",
"addBelow": "Darunter hinzufügen",
"addFilter": "Filter hinzufügen",
"adminTheme": "Admin-Farbthema",
"and": "Und",
"ascending": "Aufsteigend",
"automatic": "Automatisch",
"backToDashboard": "Zurück zur Übersicht",
"cancel": "Abbrechen",
@@ -160,6 +168,7 @@
"dark": "Dunkel",
"dashboard": "Übersicht",
"delete": "Löschen",
"deletedCountSuccessfully": "{{count}} {{label}} erfolgreich gelöscht.",
"deletedSuccessfully": "Erfolgreich gelöscht.",
"deleting": "Lösche...",
"descending": "Absteigend",
@@ -168,6 +177,9 @@
"edit": "Bearbeiten",
"editLabel": "{{label}} bearbeiten",
"editing": "Bearbeite",
"editingLabel_many": "Bearbeiten von {{count}} {{label}}",
"editingLabel_one": "Bearbeiten von {{count}} {{label}}",
"editingLabel_other": "Bearbeiten von {{count}} {{label}}",
"email": "E-Mail",
"emailAddress": "E-Mail-Adresse",
"enterAValue": "Gib einen Wert ein",
@@ -206,7 +218,9 @@
"save": "Speichern",
"saving": "Speichert...",
"searchBy": "Suche nach {{label}}",
"selectAll": "Alle auswählen {{count}} {{label}}",
"selectValue": "Wert auswählen",
"selectedCount": "{{count}} {{label}} ausgewählt",
"sorryNotFound": "Entschuldige, es entspricht nichts deiner Anfrage",
"sort": "Sortieren",
"stayOnThisPage": "Auf dieser Seite bleiben",
@@ -220,6 +234,7 @@
"unsavedChangesDuplicate": "Du hast ungespeicherte Änderungen, möchtest du mit dem Duplizieren fortfahren?",
"untitled": "ohne Titel",
"updatedAt": "Aktualisiert am",
"updatedCountSuccessfully": "{{count}} {{label}} erfolgreich aktualisiert.",
"updatedSuccessfully": "Erfolgreich aktualisiert.",
"updating": "Aktualisierung",
"uploading": "Hochladen",
@@ -228,20 +243,21 @@
"welcome": "Willkommen"
},
"operators": {
"contains": "enthält",
"equals": "gleich",
"isNotEqualTo": "ist nicht gleich",
"isIn": "ist drin",
"isNotIn": "ist nicht drin",
"exists": "existiert",
"isGreaterThan": "ist größer als",
"isGreaterThanOrEqualTo": "ist größer oder gleich",
"isIn": "ist drin",
"isLessThan": "ist kleiner als",
"isLessThanOrEqualTo": "ist kleiner oder gleich",
"isGreaterThanOrEqualTo": "ist größer oder gleich",
"near": "in der Nähe",
"isLike": "ist wie",
"contains": "enthält"
"isNotEqualTo": "ist nicht gleich",
"isNotIn": "ist nicht drin",
"near": "in der Nähe"
},
"upload": {
"dragAndDrop": "Ziehen Sie eine Datei per Drag-and-Drop",
"dragAndDropHere": "oder ziehe eine Datei hier",
"fileName": "Dateiname",
"fileSize": "Dateigröße",
@@ -250,7 +266,6 @@
"moreInfo": "Mehr Info",
"selectCollectionToBrowse": "Wähle eine Sammlung zum Durchsuchen aus",
"selectFile": "Datei auswählen",
"dragAndDrop": "Ziehen Sie eine Datei per Drag-and-Drop",
"sizes": "Größen",
"width": "Breite"
},
@@ -264,25 +279,28 @@
"invalidSelections": "'Dieses Feld enthält die folgenden inkorrekten Auswahlen:'",
"lessThanMin": "\"{{value}}\" ist weniger als der minimale erlaubte Wert von {{min}}.",
"longerThanMin": "Dieser Wert muss länger als die minimale Länge von {{minLength}} Zeichen sein.",
"requiresNoMoreThan": "Dieses Feld kann nicht mehr als {{count}} {{label}} enthalten.",
"notValidDate": "\"{{value}}\" ist kein gültiges Datum.",
"required": "Pflichtfeld",
"requiresAtLeast": "Dieses Feld muss mindestens {{count}} {{label}} enthalten.",
"requiresNoMoreThan": "Dieses Feld kann nicht mehr als {{count}} {{label}} enthalten.",
"requiresTwoNumbers": "Dieses Feld muss zwei Nummern enthalten.",
"shorterThanMax": "Dieser Wert muss kürzer als die maximale Länge von {{maxLength}} sein.",
"trueOrFalse": "Dieses Feld kann nur wahr oder falsch sein.",
"validUploadID": "'Dieses Feld enthält keine valide Upload-ID.'"
},
"version": {
"aboutToPublishSelection": "Sie sind dabei, alle {{label}} in der Auswahl zu veröffentlichen. Bist du dir sicher?",
"aboutToRestore": "Du bist dabei, {{label}} auf den Stand vom {{versionDate}} zurücksetzen.",
"aboutToRestoreGlobal": "Du bist dabei, das Globale Dokument {{label}} auf den Stand vom {{versionDate}} zurückzusetzen.",
"aboutToRevertToPublished": "Du bist dabei, dieses Dokument auf den Stand des ersten Veröffentlichungsdatums zurückzusetzen - Bist du sicher?",
"aboutToUnpublish": "Du bist dabei dieses Dokument auf Entwurf zu setzen - bist du dir sicher?",
"aboutToUnpublishSelection": "Sie sind dabei, die Veröffentlichung aller {{label}} in der Auswahl aufzuheben. Bist du dir sicher?",
"autosave": "Automatische Speicherung",
"autosavedSuccessfully": "Erfolgreich automatisch gespeichert.",
"autosavedVersion": "Automatisch gespeicherte Version",
"changed": "Geändert",
"compareVersion": "Vergleiche Version zu:",
"confirmPublish": "Veröffentlichung bestätigen",
"confirmRevertToSaved": "Zurücksetzen auf die letzte Speicherung bestätigen",
"confirmUnpublish": "Setzen auf Entwurf bestätigen",
"confirmVersionRestoration": " Wiederherstellung der Version bestätigen",
@@ -294,6 +312,7 @@
"noRowsFound": "Kein {{label}} gefunden",
"preview": "Vorschau",
"problemRestoringVersion": "Es gab ein Problem bei der Wiederherstellung dieser Version",
"publish": "Veröffentlichen",
"publishChanges": "Änderungen veröffentlichen",
"published": "Veröffentlicht",
"restoreThisVersion": "Diese Version wiederherstellen",
@@ -305,6 +324,7 @@
"selectLocales": "Wähle anzuzeigende Sprachumgebungen",
"selectVersionToCompare": "Wähle Version zum Vergleich",
"showLocales": "Sprachumgebungen anzeigen:",
"showingVersionsFor": "Versionen anzeigen für:",
"status": "Status",
"type": "Typ",
"unpublish": "Auf Entwurf setzen",
@@ -313,6 +333,7 @@
"versionCount_many": "{{count}} Versionen gefunden",
"versionCount_none": "Keine Versionen gefunden",
"versionCount_one": "{{count}} Version gefunden",
"versionCount_other": "{{count}} Versionen gefunden",
"versionCreatedOn": "{{version}} erstellt am:",
"versionID": "Version ID",
"versions": "Versionen",

View File

@@ -82,6 +82,8 @@
"problemUploadingFile": "There was a problem while uploading the file.",
"tokenInvalidOrExpired": "Token is either invalid or has expired.",
"unPublishingDocument": "There was a problem while un-publishing this document.",
"unableToDeleteCount": "Unable to delete {{count}} out of {{total}} {{label}}.",
"unableToUpdateCount": "Unable to update {{count}} out of {{total}} {{label}}.",
"unauthorized": "Unauthorized, you must be logged in to make this request.",
"unknown": "An unknown error has occurred.",
"unspecific": "An error has occurred.",
@@ -126,6 +128,7 @@
"saveChanges": "Save changes",
"searchForBlock": "Search for a block",
"selectExistingLabel": "Select existing {{label}}",
"selectFieldsToEdit": "Select fields to edit",
"showAll": "Show All",
"swapRelationship": "Swap Relationship",
"swapUpload": "Swap Upload",
@@ -135,6 +138,9 @@
},
"general": {
"aboutToDelete": "You are about to delete the {{label}} <1>{{title}}</1>. Are you sure?",
"aboutToDeleteCount_many": "You are about to delete {{count}} {{label}}",
"aboutToDeleteCount_one": "You are about to delete {{count}} {{label}}",
"aboutToDeleteCount_other": "You are about to delete {{count}} {{label}}",
"addBelow": "Add Below",
"addFilter": "Add Filter",
"adminTheme": "Admin Theme",
@@ -162,6 +168,7 @@
"dark": "Dark",
"dashboard": "Dashboard",
"delete": "Delete",
"deletedCountSuccessfully": "Deleted {{count}} {{label}} successfully.",
"deletedSuccessfully": "Deleted successfully.",
"deleting": "Deleting...",
"descending": "Descending",
@@ -170,6 +177,9 @@
"edit": "Edit",
"editLabel": "Edit {{label}}",
"editing": "Editing",
"editingLabel_many": "Editing {{count}} {{label}}",
"editingLabel_one": "Editing {{count}} {{label}}",
"editingLabel_other": "Editing {{count}} {{label}}",
"email": "Email",
"emailAddress": "Email Address",
"enterAValue": "Enter a value",
@@ -208,7 +218,9 @@
"save": "Save",
"saving": "Saving...",
"searchBy": "Search by {{label}}",
"selectAll": "Select all {{count}} {{label}}",
"selectValue": "Select a value",
"selectedCount": "{{count}} {{label}} selected",
"sorryNotFound": "Sorry—there is nothing to correspond with your request.",
"sort": "Sort",
"stayOnThisPage": "Stay on this page",
@@ -222,6 +234,7 @@
"unsavedChangesDuplicate": "You have unsaved changes. Would you like to continue to duplicate?",
"untitled": "Untitled",
"updatedAt": "Updated At",
"updatedCountSuccessfully": "Updated {{count}} {{label}} successfully.",
"updatedSuccessfully": "Updated successfully.",
"updating": "Updating",
"uploading": "Uploading",
@@ -230,20 +243,21 @@
"welcome": "Welcome"
},
"operators": {
"contains": "contains",
"equals": "equals",
"isNotEqualTo": "is not equal to",
"isIn": "is in",
"isNotIn": "is not in",
"exists": "exists",
"isGreaterThan": "is greater than",
"isGreaterThanOrEqualTo": "is greater than or equal to",
"isIn": "is in",
"isLessThan": "is less than",
"isLessThanOrEqualTo": "is less than or equal to",
"isGreaterThanOrEqualTo": "is greater than or equal to",
"near": "near",
"isLike": "is like",
"contains": "contains"
"isNotEqualTo": "is not equal to",
"isNotIn": "is not in",
"near": "near"
},
"upload": {
"dragAndDrop": "Drag and drop a file",
"dragAndDropHere": "or drag and drop a file here",
"fileName": "File Name",
"fileSize": "File Size",
@@ -252,7 +266,6 @@
"moreInfo": "More info",
"selectCollectionToBrowse": "Select a Collection to Browse",
"selectFile": "Select a file",
"dragAndDrop": "Drag and drop a file",
"sizes": "Sizes",
"width": "Width"
},
@@ -276,15 +289,18 @@
"validUploadID": "This field is not a valid upload ID."
},
"version": {
"aboutToPublishSelection": "You are about to publish all {{label}} in the selection. Are you sure?",
"aboutToRestore": "You are about to restore this {{label}} document to the state that it was in on {{versionDate}}.",
"aboutToRestoreGlobal": "You are about to restore the global {{label}} to the state that it was in on {{versionDate}}.",
"aboutToRevertToPublished": "You are about to revert this document's changes to its published state. Are you sure?",
"aboutToUnpublish": "You are about to unpublish this document. Are you sure?",
"aboutToUnpublishSelection": "You are about to unpublish all {{label}} in the selection. Are you sure?",
"autosave": "Autosave",
"autosavedSuccessfully": "Autosaved successfully.",
"autosavedVersion": "Autosaved version",
"changed": "Changed",
"compareVersion": "Compare version against:",
"confirmPublish": "Confirm publish",
"confirmRevertToSaved": "Confirm revert to saved",
"confirmUnpublish": "Confirm unpublish",
"confirmVersionRestoration": "Confirm version Restoration",
@@ -296,6 +312,7 @@
"noRowsFound": "No {{label}} found",
"preview": "Preview",
"problemRestoringVersion": "There was a problem restoring this version",
"publish": "Publish",
"publishChanges": "Publish changes",
"published": "Published",
"restoreThisVersion": "Restore this version",
@@ -306,8 +323,8 @@
"saveDraft": "Save Draft",
"selectLocales": "Select locales to display",
"selectVersionToCompare": "Select a version to compare",
"showingVersionsFor": "Showing versions for:",
"showLocales": "Show locales:",
"showingVersionsFor": "Showing versions for:",
"status": "Status",
"type": "Type",
"unpublish": "Unpublish",

View File

@@ -82,6 +82,8 @@
"problemUploadingFile": "Ocurrió un problema al subir el archivo.",
"tokenInvalidOrExpired": "El token es inválido o ya expiró.",
"unPublishingDocument": "Ocurrió un error al despublicar este documento.",
"unableToDeleteCount": "No se pudo eliminar {{count}} de {{total}} {{label}}.",
"unableToUpdateCount": "No se puede actualizar {{count}} de {{total}} {{label}}.",
"unauthorized": "No autorizado, debes iniciar sesión para realizar esta solicitud.",
"unknown": "Ocurrió un error desconocido.",
"unspecific": "Ocurrió un error.",
@@ -126,6 +128,7 @@
"saveChanges": "Guardar cambios",
"searchForBlock": "Buscar bloque",
"selectExistingLabel": "Seleccionar {{label}} existente",
"selectFieldsToEdit": "Seleccionar campos para editar",
"showAll": "Mostrar Todo",
"swapRelationship": "Cambiar Relación",
"swapUpload": "Cambiar carga",
@@ -135,6 +138,9 @@
},
"general": {
"aboutToDelete": "Estás por eliminar el {{label}} <1>{{title}}</1>. ¿Estás seguro?",
"aboutToDeleteCount_many": "Está a punto de eliminar {{count}} {{label}}",
"aboutToDeleteCount_one": "Está a punto de eliminar {{count}} {{label}}",
"aboutToDeleteCount_other": "Está a punto de eliminar {{count}} {{label}}",
"addBelow": "Agrega abajo",
"addFilter": "Añadir filtro",
"adminTheme": "Tema del admin",
@@ -162,6 +168,7 @@
"dark": "Oscuro",
"dashboard": "Tablero",
"delete": "Eliminar",
"deletedCountSuccessfully": "Se eliminó {{count}} {{label}} con éxito.",
"deletedSuccessfully": "Borrado exitosamente.",
"deleting": "Eliminando...",
"descending": "Descendente",
@@ -170,6 +177,9 @@
"edit": "Editar",
"editLabel": "Editar {{label}}",
"editing": "Editando",
"editingLabel_many": "Edición de {{count}} {{label}}",
"editingLabel_one": "Editando {{count}} {{label}}",
"editingLabel_other": "Edición de {{count}} {{label}}",
"email": "Correo electrónico",
"emailAddress": "Dirección de Correo Electrónico",
"enterAValue": "Introduce un valor",
@@ -208,7 +218,9 @@
"save": "Guardar",
"saving": "Guardando...",
"searchBy": "Buscar por {{label}}",
"selectAll": "Seleccionar todo {{count}} {{label}}",
"selectValue": "Selecciona un valor",
"selectedCount": "{{count}} {{label}} seleccionado",
"sorryNotFound": "Lo sentimos. No hay nada que corresponda con tu solicitud.",
"sort": "Ordenar",
"stayOnThisPage": "Permanecer en esta página",
@@ -222,6 +234,7 @@
"unsavedChangesDuplicate": "Tienes cambios sin guardar. ¿Deseas continuar para duplicar?",
"untitled": "Sin título",
"updatedAt": "Fecha de modificado",
"updatedCountSuccessfully": "{{count}} {{label}} actualizado con éxito.",
"updatedSuccessfully": "Actualizado con éxito.",
"updating": "Actualizando",
"uploading": "Subiendo",
@@ -230,20 +243,21 @@
"welcome": "Bienvenido"
},
"operators": {
"contains": "contiene",
"equals": "igual",
"isNotEqualTo": "no es igual a",
"isIn": "está en",
"isNotIn": "no está en",
"exists": "existe",
"isGreaterThan": "es mayor que",
"isGreaterThanOrEqualTo": "es mayor o igual que",
"isIn": "está en",
"isLessThan": "es menor que",
"isLessThanOrEqualTo": "es menor o igual que",
"isGreaterThanOrEqualTo": "es mayor o igual que",
"near": "cerca",
"isLike": "es como",
"contains": "contiene"
"isNotEqualTo": "no es igual a",
"isNotIn": "no está en",
"near": "cerca"
},
"upload": {
"dragAndDrop": "Arrastra y suelta un archivo",
"dragAndDropHere": "o arrastra un archivo aquí",
"fileName": "Nombre del archivo",
"fileSize": "Tamaño del archivo",
@@ -252,7 +266,6 @@
"moreInfo": "Más info",
"selectCollectionToBrowse": "Selecciona una Colección",
"selectFile": "Selecciona un archivo",
"dragAndDrop": "Arrastra y suelta un archivo",
"sizes": "Tamaños",
"width": "Ancho"
},
@@ -276,15 +289,18 @@
"validUploadID": "'Este campo no es una ID de subida válida.'"
},
"version": {
"aboutToPublishSelection": "Está a punto de publicar todas las {{etiquetas}} de la selección. ¿Está seguro?",
"aboutToRestore": "Estás a punto de restaurar este documento de {{label}} al estado en el que estaba en la fecha {{versionDate}}.",
"aboutToRestoreGlobal": "Estás a punto de restaurar el {{label}} global al estado en el que estaba en la fecha {{versionDate}}.",
"aboutToRevertToPublished": "Estás a punto de revertir los cambios de este documento a su estado publicado. ¿Estás seguro?",
"aboutToUnpublish": "Estás a punto de despublicar este documento. ¿Estás seguro?",
"aboutToUnpublishSelection": "Está a punto de anular la publicación de todos los {{label}} de la selección. ¿Está seguro?",
"autosave": "Autoguardar",
"autosavedSuccessfully": "Guardado automáticamente con éxito.",
"autosavedVersion": "Versión Autoguardada",
"changed": "Modificado",
"compareVersion": "Comparar versión con:",
"confirmPublish": "Confirmar publicación",
"confirmRevertToSaved": "Confirmar revertir a guardado",
"confirmUnpublish": "Confirmar despublicado",
"confirmVersionRestoration": "Confirmar restauración de versión",
@@ -296,6 +312,7 @@
"noRowsFound": "No encontramos {{label}}",
"preview": "Previsualizar",
"problemRestoringVersion": "Ocurrió un problema al restaurar esta versión",
"publish": "Publicar",
"publishChanges": "Publicar cambios",
"published": "Publicado",
"restoreThisVersion": "Restaurar esta versión",
@@ -306,8 +323,8 @@
"saveDraft": "Guardar Borrador",
"selectLocales": "Selecciona idiomas a mostrar",
"selectVersionToCompare": "Selecciona versión a comparar",
"showingVersionsFor": "Mostrando versiones para:",
"showLocales": "Mostrar idiomas:",
"showingVersionsFor": "Mostrando versiones para:",
"status": "Estado",
"type": "Tipo",
"unpublish": "Despublicar",

View File

@@ -82,6 +82,8 @@
"problemUploadingFile": "Il y a eu un problème lors du téléversement du fichier.",
"tokenInvalidOrExpired": "Le jeton n'est soit pas valide ou a expiré.",
"unPublishingDocument": "Un problème est survenu lors de l'annulation de la publication de ce document.",
"unableToDeleteCount": "Impossible de supprimer {{count}} sur {{total}} {{label}}.",
"unableToUpdateCount": "Impossible de mettre à jour {{count}} sur {{total}} {{label}}.",
"unauthorized": "Non autorisé, vous devez être connecté pour effectuer cette demande.",
"unknown": "Une erreur inconnue s'est produite.",
"unspecific": "Une erreur est survenue.",
@@ -90,15 +92,15 @@
"verificationTokenInvalid": "Le jeton de vérification n'est pas valide."
},
"fields": {
"block": "bloc",
"blocks": "blocs",
"addLabel": "Ajouter {{label}}",
"addLink": "Ajouter un Lien",
"addNew": "Ajouter nouveau ou nouvelle",
"addNewLabel": "Ajouter nouveau ou nouvelle {{label}}",
"addRelationship": "Ajouter une relation",
"addUpload": "Ajouter le téléchargement",
"block": "bloc",
"blockType": "Type de bloc",
"blocks": "blocs",
"chooseBetweenCustomTextOrDocument": "Choisissez entre saisir une URL personnalisée ou créer un lien vers un autre document.",
"chooseDocumentToLink": "Choisissez un document vers lequel établir un lien",
"chooseFromExisting": "Choisir parmi les existant(e)s",
@@ -126,6 +128,7 @@
"saveChanges": "Sauvegarder les modifications",
"searchForBlock": "Rechercher un bloc",
"selectExistingLabel": "Sélectionnez {{label}} existant",
"selectFieldsToEdit": "Sélectionnez les champs à modifier",
"showAll": "Afficher tout",
"swapRelationship": "Changer de relation",
"swapUpload": "Changer de Fichier",
@@ -135,10 +138,14 @@
},
"general": {
"aboutToDelete": "Vous êtes sur le point de supprimer ce ou cette {{label}} <1>{{title}}</1>. Êtes-vous sûr ?",
"aboutToDeleteCount_many": "Vous êtes sur le point de supprimer {{count}} {{label}}",
"aboutToDeleteCount_one": "Vous êtes sur le point de supprimer {{count}} {{label}}",
"aboutToDeleteCount_other": "Vous êtes sur le point de supprimer {{count}} {{label}}",
"addBelow": "Ajoutez ci-dessous",
"addFilter": "Ajouter un filtre",
"adminTheme": "Thème d'administration",
"and": "Et",
"ascending": "Ascendant",
"automatic": "Automatique",
"backToDashboard": "Retour au tableau de bord",
"cancel": "Annuler",
@@ -161,6 +168,7 @@
"dark": "Nuit",
"dashboard": "Tableau de bord",
"delete": "Supprimer",
"deletedCountSuccessfully": "{{count}} {{label}} supprimé avec succès.",
"deletedSuccessfully": "Supprimé(e) avec succès.",
"deleting": "Suppression en cours...",
"descending": "Descendant(e)",
@@ -169,6 +177,9 @@
"edit": "Éditer",
"editLabel": "Modifier {{label}}",
"editing": "Modification en cours",
"editingLabel_many": "Modification des {{count}} {{label}}",
"editingLabel_one": "Modification de {{count}} {{label}}",
"editingLabel_other": "Modification des {{count}} {{label}}",
"email": "E-mail",
"emailAddress": "Adresse e-mail",
"enterAValue": "Entrez une valeur",
@@ -207,7 +218,9 @@
"save": "Sauvegarder",
"saving": "Sauvegarde en cours...",
"searchBy": "Rechercher par {{label}}",
"selectAll": "Tout sélectionner {{count}} {{label}}",
"selectValue": "Sélectionnez une valeur",
"selectedCount": "{{count}} {{label}} sélectionné",
"sorryNotFound": "Désolé, rien ne correspond à votre demande.",
"sort": "Trier",
"stayOnThisPage": "Rester sur cette page",
@@ -221,6 +234,7 @@
"unsavedChangesDuplicate": "Vous avez des changements non enregistrés. Souhaitez-vous continuer la duplication ?",
"untitled": "Sans titre",
"updatedAt": "Modifié le",
"updatedCountSuccessfully": "{{count}} {{label}} mis à jour avec succès.",
"updatedSuccessfully": "Mis à jour avec succés.",
"updating": "Mise à jour",
"uploading": "Téléchargement",
@@ -229,20 +243,21 @@
"welcome": "Bienvenu(e)"
},
"operators": {
"contains": "contient",
"equals": "est égal à",
"isNotEqualTo": "n'est pas égal à",
"isIn": "est dans",
"isNotIn": "n'est pas dans",
"exists": "existe",
"isGreaterThan": "est supérieur à",
"isGreaterThanOrEqualTo": "est supérieur ou égal à",
"isIn": "est dans",
"isLessThan": "est inférieur à",
"isLessThanOrEqualTo": "est inférieur ou égal à",
"isGreaterThanOrEqualTo": "est supérieur ou égal à",
"near": "proche",
"isLike": "est comme",
"contains": "contient"
"isNotEqualTo": "n'est pas égal à",
"isNotIn": "n'est pas dans",
"near": "proche"
},
"upload": {
"dragAndDrop": "Glisser-déposer un fichier",
"dragAndDropHere": "ou glissez-déposez un fichier ici",
"fileName": "Nom du fichier",
"fileSize": "Taille du fichier",
@@ -251,7 +266,6 @@
"moreInfo": "Plus d'infos",
"selectCollectionToBrowse": "Sélectionnez une collection à parcourir",
"selectFile": "Sélectionnez un fichier",
"dragAndDrop": "Glisser-déposer un fichier",
"sizes": "Tailles",
"width": "Largeur"
},
@@ -275,15 +289,18 @@
"validUploadID": "Ce champ n'est pas un valide identifiant de fichier."
},
"version": {
"aboutToPublishSelection": "Vous êtes sur le point de publier tous les {{label}} de la sélection. Es-tu sûr?",
"aboutToRestore": "Vous êtes sur le point de restaurer le document {{label}} à l'état où il se trouvait le {{versionDate}}.",
"aboutToRestoreGlobal": "Vous êtes sur le point de restaurer le ou la {{label}} global(e) à l'état où il ou elle se trouvait le {{versionDate}}.",
"aboutToRevertToPublished": "Vous êtes sur le point de rétablir les modifications apportées à ce document à la version publiée. Êtes-vous sûr ?",
"aboutToUnpublish": "Vous êtes sur le point d'annuler la publication de ce document. Êtes-vous sûr ?",
"aboutToUnpublishSelection": "Vous êtes sur le point de dépublier tous les {{label}} de la sélection. Es-tu sûr?",
"autosave": "Enregistrement automatique",
"autosavedSuccessfully": "Enregistrement automatique réussi.",
"autosavedVersion": "Version enregistrée automatiquement",
"changed": "Modifié",
"compareVersion": "Comparez cette version à :",
"confirmPublish": "Confirmer la publication",
"confirmRevertToSaved": "Confirmer la restauration",
"confirmUnpublish": "Confirmer l'annulation",
"confirmVersionRestoration": "Confirmer la restauration de la version",
@@ -295,6 +312,7 @@
"noRowsFound": "Aucun(e) {{label}} trouvé(e)",
"preview": "Aperçu",
"problemRestoringVersion": "Un problème est survenu lors de la restauration de cette version",
"publish": "Publier",
"publishChanges": "Publier les modifications",
"published": "Publié",
"restoreThisVersion": "Restaurer cette version",
@@ -303,9 +321,10 @@
"revertToPublished": "Republier",
"reverting": "Republication en cours...",
"saveDraft": "Enregistrer le brouillon",
"selectLocals": "Sélectionnez les paramètres régionaux à afficher",
"selectLocales": "Sélectionnez les paramètres régionaux à afficher",
"selectVersionToCompare": "Sélectionnez une version à comparer",
"showLocales": "Afficher les paramètres régionaux :",
"showingVersionsFor": "Affichage des versions pour :",
"status": "Statut",
"type": "Type",
"unpublish": "Annuler la publication",
@@ -314,6 +333,7 @@
"versionCount_many": "{{count}} versions trouvées",
"versionCount_none": "Aucune version trouvée",
"versionCount_one": "{{count}} version trouvée",
"versionCount_other": "{{count}} versions trouvées",
"versionCreatedOn": "{{version}} créé(e) le :",
"versionID": "Identifiant de la version",
"versions": "Versions",

View File

@@ -82,6 +82,8 @@
"problemUploadingFile": "Pojavio se problem pri učitavanju datoteke.",
"tokenInvalidOrExpired": "Token je nevaljan ili je istekao.",
"unPublishingDocument": "Pojavio se problem pri poništavanju objave ovog dokumenta.",
"unableToDeleteCount": "Nije moguće izbrisati {{count}} od {{total}} {{label}}.",
"unableToUpdateCount": "Nije moguće ažurirati {{count}} od {{total}} {{label}}.",
"unauthorized": "Neovlašten, morate biti prijavljeni da biste uputili ovaj zahtjev.",
"unknown": "Došlo je do nepoznate pogreške.",
"unspecific": "Došlo je do pogreške.",
@@ -126,6 +128,7 @@
"saveChanges": "Spremi promjene",
"searchForBlock": "Potraži blok",
"selectExistingLabel": "Odaberi postojeće{{label}}",
"selectFieldsToEdit": "Odaberite polja za uređivanje",
"showAll": "Pokaži sve",
"swapRelationship": "Zamijeni vezu",
"swapUpload": "Zamijeni prijenos",
@@ -135,6 +138,9 @@
},
"general": {
"aboutToDelete": "Izbrisat ćete {{label}} <1>{{title}}</1>. Jeste li sigurni?",
"aboutToDeleteCount_many": "Upravo ćete izbrisati {{count}} {{label}}",
"aboutToDeleteCount_one": "Upravo ćete izbrisati {{count}} {{label}}",
"aboutToDeleteCount_other": "Upravo ćete izbrisati {{count}} {{label}}",
"addBelow": "Dodaj ispod",
"addFilter": "Dodaj filter",
"adminTheme": "Administratorska tema",
@@ -162,6 +168,7 @@
"dark": "Tamno",
"dashboard": "Nadzorna ploča",
"delete": "Obriši",
"deletedCountSuccessfully": "Uspješno izbrisano {{count}} {{label}}.",
"deletedSuccessfully": "Uspješno obrisano.",
"deleting": "Brisanje...",
"descending": "Silazno",
@@ -170,6 +177,9 @@
"edit": "Uredi",
"editLabel": "Uredi {{label}}",
"editing": "Uređivanje",
"editingLabel_many": "Uređivanje {{count}} {{label}}",
"editingLabel_one": "Uređivanje {{count}} {{label}}",
"editingLabel_other": "Uređivanje {{count}} {{label}}",
"email": "Email",
"emailAddress": "Email adresa",
"enterAValue": "Unesi vrijednost",
@@ -208,7 +218,9 @@
"save": "Spremi",
"saving": "Spremanje...",
"searchBy": "Traži po {{label}}",
"selectAll": "Odaberite sve {{count}} {{label}}",
"selectValue": "Odaberi vrijednost",
"selectedCount": "{{count}} {{label}} odabrano",
"sorryNotFound": "Nažalost, ne postoji ništa što odgovara vašem zahtjevu.",
"sort": "Sortiraj",
"stayOnThisPage": "Ostani na ovoj stranici",
@@ -222,6 +234,7 @@
"unsavedChangesDuplicate": "Imate nespremljene promjene. Želite li nastaviti s dupliciranjem?",
"untitled": "Bez naslova",
"updatedAt": "Ažurirano u",
"updatedCountSuccessfully": "Uspješno ažurirano {{count}} {{label}}.",
"updatedSuccessfully": "Uspješno ažurirano.",
"updating": "Ažuriranje",
"uploading": "Prijenos",
@@ -230,20 +243,21 @@
"welcome": "Dobrodošli"
},
"operators": {
"contains": "sadrži",
"equals": "jednako",
"isNotEqualTo": "nije jednako",
"isIn": "je u",
"isNotIn": "nije unutra",
"exists": "postoji",
"isGreaterThan": "je veće od",
"isGreaterThanOrEqualTo": "je veće od ili jednako",
"isIn": "je u",
"isLessThan": "manje je od",
"isLessThanOrEqualTo": "manje je ili jednako",
"isGreaterThanOrEqualTo": "je veće od ili jednako",
"near": "blizu",
"isLike": "je kao",
"contains": "sadrži"
"isNotEqualTo": "nije jednako",
"isNotIn": "nije unutra",
"near": "blizu"
},
"upload": {
"dragAndDrop": "Povucite i ispustite datoteku",
"dragAndDropHere": "ili povucite i ispustite datoteku ovdje",
"fileName": "Ime datoteke",
"fileSize": "Veličina datoteke",
@@ -252,7 +266,6 @@
"moreInfo": "Više informacija",
"selectCollectionToBrowse": "Odaberite kolekciju za pregled",
"selectFile": "Odaberite datoteku",
"dragAndDrop": "Povucite i ispustite datoteku",
"sizes": "Veličine",
"width": "Širina"
},
@@ -276,15 +289,18 @@
"validUploadID": "Ovo polje nije valjani ID prijenosa."
},
"version": {
"aboutToPublishSelection": "Upravo ćete objaviti sve {{label}} u izboru. Jesi li siguran?",
"aboutToRestore": "Vratit ćete {{label}} dokument u stanje u kojem je bio {{versionDate}}",
"aboutToRestoreGlobal": "Vratit ćete globalni {{label}} u stanje u kojem je bio {{versionDate}}.",
"aboutToRevertToPublished": "Vratit ćete promjene u dokumentu u objavljeno stanje. Jeste li sigurni? ",
"aboutToUnpublish": "Poništit ćete objavu ovog dokumenta. Jeste li sigurni?",
"aboutToUnpublishSelection": "Upravo ćete poništiti objavu svih {{label}} u odabiru. Jesi li siguran?",
"autosave": "Automatsko spremanje",
"autosavedSuccessfully": "Automatsko spremanje uspješno.",
"autosavedVersion": "Verzija automatski spremljenog dokumenta",
"changed": "Promijenjeno",
"compareVersion": "Usporedi verziju sa:",
"confirmPublish": "Potvrdi objavu",
"confirmRevertToSaved": "Potvrdite vraćanje na spremljeno",
"confirmUnpublish": "Potvrdite poništavanje objave",
"confirmVersionRestoration": "Potvrdite vraćanje verzije",
@@ -296,6 +312,7 @@
"noRowsFound": "{{label}} nije pronađeno",
"preview": "Pregled",
"problemRestoringVersion": "Nastao je problem pri vraćanju ove verzije",
"publish": "Objaviti",
"publishChanges": "Objavi promjene",
"published": "Objavljeno",
"restoreThisVersion": "Vrati ovu verziju",
@@ -306,8 +323,8 @@
"saveDraft": "Sačuvaj nacrt",
"selectLocales": "Odaberite jezike",
"selectVersionToCompare": "Odaberite verziju za usporedbu",
"showingVersionsFor": "Pokazujem verzije za:",
"showLocales": "Prikaži jezike:",
"showingVersionsFor": "Pokazujem verzije za:",
"status": "Status",
"type": "Tip",
"unpublish": "Poništi objavu",

View File

@@ -82,6 +82,8 @@
"problemUploadingFile": "Hiba történt a fájl feltöltése közben.",
"tokenInvalidOrExpired": "A token érvénytelen vagy lejárt.",
"unPublishingDocument": "Hiba történt a dokumentum közzétételének visszavonása közben.",
"unableToDeleteCount": "Nem sikerült törölni {{count}}/{{total}} {{label}}.",
"unableToUpdateCount": "Nem sikerült frissíteni {{count}}/{{total}} {{label}}.",
"unauthorized": "Jogosulatlan, a kéréshez be kell jelentkeznie.",
"unknown": "Ismeretlen hiba történt.",
"unspecific": "Hiba történt.",
@@ -126,6 +128,7 @@
"saveChanges": "Módosítások mentése",
"searchForBlock": "Blokk keresése",
"selectExistingLabel": "Meglévő {{label}} kiválasztása",
"selectFieldsToEdit": "Válassza ki a szerkeszteni kívánt mezőket",
"showAll": "Az összes megjelenítése",
"swapRelationship": "Kapcsolat csere",
"swapUpload": "Feltöltés csere",
@@ -135,6 +138,9 @@
},
"general": {
"aboutToDelete": "A {{label}} <1>{{title}}</1> törlésére készül. Biztos benne?",
"aboutToDeleteCount_many": "Törölni készül {{count}} {{label}}",
"aboutToDeleteCount_one": "Törölni készül {{count}} {{label}}",
"aboutToDeleteCount_other": "Törölni készül {{count}} {{label}}",
"addBelow": "Hozzáadás lent",
"addFilter": "Szűrő hozzáadása",
"adminTheme": "Admin téma",
@@ -162,6 +168,7 @@
"dark": "Sötét",
"dashboard": "Irányítópult",
"delete": "Törlés",
"deletedCountSuccessfully": "{{count}} {{label}} sikeresen törölve.",
"deletedSuccessfully": "Sikeresen törölve.",
"deleting": "Törlés...",
"descending": "Csökkenő",
@@ -170,6 +177,9 @@
"edit": "Szerkesztés",
"editLabel": "{{label}} szerkesztése",
"editing": "Szerkesztés",
"editingLabel_many": "{{count}} {{label}} szerkesztése",
"editingLabel_one": "{{count}} {{label}} szerkesztése",
"editingLabel_other": "{{count}} {{label}} szerkesztése",
"email": "E-mail",
"emailAddress": "E-mail cím",
"enterAValue": "Adjon meg egy értéket",
@@ -208,7 +218,9 @@
"save": "Mentés",
"saving": "Mentés...",
"searchBy": "Keresés a következő szerint: {{label}}",
"selectAll": "Az összes kijelölése: {{count}} {{label}}",
"selectValue": "Válasszon ki egy értéket",
"selectedCount": "{{count}} {{label}} kiválasztva",
"sorryNotFound": "Sajnáljuk nincs semmi, ami megfelelne a kérésének.",
"sort": "Rendezés",
"stayOnThisPage": "Maradjon ezen az oldalon",
@@ -222,6 +234,7 @@
"unsavedChangesDuplicate": "Nem mentett módosításai vannak. Szeretné folytatni a duplikációt?",
"untitled": "Névtelen",
"updatedAt": "Frissítve:",
"updatedCountSuccessfully": "{{count}} {{label}} sikeresen frissítve.",
"updatedSuccessfully": "Sikeresen frissítve.",
"updating": "Frissítés",
"uploading": "Feltöltés",
@@ -276,15 +289,18 @@
"validUploadID": "Ez a mező nem érvényes feltöltési azonosító."
},
"version": {
"aboutToPublishSelection": "Arra készül, hogy az összes {{label}} elemet közzétegye a kijelölésben. biztos vagy ebben?",
"aboutToRestore": "Arra készül, hogy visszaállítsa ezt a {{label}} dokumentumot arra az állapotra, amelyben {{versionDate}} napon volt.",
"aboutToRestoreGlobal": "Arra készül, hogy visszaállítsa a {{label}} arra az állapotra, amelyben {{versionDate}} napon volt.",
"aboutToRevertToPublished": "Arra készül, hogy visszaállítsa a dokumentum módosításait a közzétett állapotába. Biztos benne?",
"aboutToUnpublish": "A dokumentum közzétételének visszavonására készül. Biztos benne?",
"aboutToUnpublishSelection": "Arra készül, hogy visszavonja a kijelölésben szereplő összes {{label}} közzétételét. biztos vagy ebben?",
"autosave": "Automatikus mentés",
"autosavedSuccessfully": "Automatikus mentés sikeres.",
"autosavedVersion": "Automatikusan mentett verzió",
"changed": "Megváltozott",
"compareVersion": "Hasonlítsa össze a verziót a következőkkel:",
"confirmPublish": "A közzététel megerősítése",
"confirmRevertToSaved": "Erősítse meg a mentett verzióra való visszatérést",
"confirmUnpublish": "A közzététel visszavonásának megerősítése",
"confirmVersionRestoration": "Verzió-visszaállítás megerősítése",
@@ -296,6 +312,7 @@
"noRowsFound": "Nem található {{label}}",
"preview": "Előnézet",
"problemRestoringVersion": "Hiba történt a verzió visszaállításakor",
"publish": "Közzététel",
"publishChanges": "Módosítások közzététele",
"published": "Közzétett",
"restoreThisVersion": "A verzió visszaállítása",
@@ -306,8 +323,8 @@
"saveDraft": "Piszkozat mentése",
"selectLocales": "Megjelenítendő nyelvek kiválasztása",
"selectVersionToCompare": "Válassza ki az összehasonlítani kívánt verziót",
"showingVersionsFor": "Verziók megjelenítése a következőkhöz:",
"showLocales": "Nyelvek megjelenítése:",
"showingVersionsFor": "Verziók megjelenítése a következőkhöz:",
"status": "Állapot",
"type": "Típus",
"unpublish": "Közzététel visszavonása",

View File

@@ -82,6 +82,8 @@
"problemUploadingFile": "Si è verificato un problema durante il caricamento del file.",
"tokenInvalidOrExpired": "Il token non è valido o è scaduto.",
"unPublishingDocument": "Si è verificato un problema durante l'annullamento della pubblicazione di questo documento.",
"unableToDeleteCount": "Impossibile eliminare {{count}} su {{total}} {{label}}.",
"unableToUpdateCount": "Impossibile aggiornare {{count}} su {{total}} {{label}}.",
"unauthorized": "Non autorizzato, devi essere loggato per effettuare questa richiesta.",
"unknown": "Si è verificato un errore sconosciuto.",
"unspecific": "Si è verificato un errore.",
@@ -90,27 +92,34 @@
"verificationTokenInvalid": "Il token di verifica non è valido."
},
"fields": {
"block": "blocco",
"blocks": "blocchi",
"addLabel": "Aggiungi {{label}}",
"addLink": "Aggiungi Collegamento",
"addNew": "Aggiungi nuovo",
"addNewLabel": "Aggiungi nuovo {{label}}",
"addRelationship": "Aggiungi Relazione",
"addUpload": "aggiungi Carica",
"block": "blocco",
"blockType": "Tipo di Blocco",
"blocks": "blocchi",
"chooseBetweenCustomTextOrDocument": "Scegli tra l'inserimento di un URL di testo personalizzato o il collegamento a un altro documento.",
"chooseDocumentToLink": "Scegli un documento a cui collegarti",
"chooseFromExisting": "Scegli tra esistente",
"chooseLabel": "Scegli {{label}}",
"collapseAll": "Comprimi tutto",
"customURL": "URL personalizzato",
"editLabelData": "Modifica i dati di {{label}}",
"editLink": "Modifica Collegamento",
"editRelationship": "Modifica Relazione",
"enterURL": "Inserisci un URL",
"internalLink": "Collegamento interno",
"itemsAndMore": "{{items}} e altri {{count}}",
"labelRelationship": "Relazione {{label}}",
"latitude": "Latitudine",
"linkType": "Tipo di collegamento",
"linkedTo": "Collegato a <0>{{label}}</0>",
"longitude": "Longitudine",
"newLabel": "Nuovo {{label}}",
"openInNewTab": "Apri in una nuova scheda",
"passwordsDoNotMatch": "Le password non corrispondono.",
"relatedDocument": "Documento Correlato",
"relationTo": "Correla a",
@@ -119,18 +128,24 @@
"saveChanges": "Salva modifiche",
"searchForBlock": "Cerca un blocco",
"selectExistingLabel": "Seleziona {{label}} esistente",
"selectFieldsToEdit": "Seleziona i campi da modificare",
"showAll": "Mostra tutto",
"swapRelationship": "Cambia Relationship",
"swapUpload": "Cambia Upload",
"textToDisplay": "Testo da visualizzare",
"toggleBlock": "Apri/chiudi blocco",
"uploadNewLabel": "Carica nuovo {{label}}"
},
"general": {
"aboutToDelete": "Stai per eliminare {{label}} <1>{{title}}</1>. Sei sicuro?",
"aboutToDeleteCount_many": "Stai per eliminare {{count}} {{label}}",
"aboutToDeleteCount_one": "Stai per eliminare {{count}} {{label}}",
"aboutToDeleteCount_other": "Stai per eliminare {{count}} {{label}}",
"addBelow": "Aggiungi sotto",
"addFilter": "Aggiungi Filtro",
"adminTheme": "Tema Admin",
"and": "E",
"ascending": "Ascendente",
"automatic": "Automatico",
"backToDashboard": "Torna alla Dashboard",
"cancel": "Cancella",
@@ -153,6 +168,7 @@
"dark": "Scuro",
"dashboard": "Dashboard",
"delete": "Elimina",
"deletedCountSuccessfully": "{{count}} {{label}} eliminato con successo.",
"deletedSuccessfully": "Eliminato con successo.",
"deleting": "Sto eliminando...",
"descending": "Decrescente",
@@ -161,6 +177,9 @@
"edit": "Modificare",
"editLabel": "Modifica {{label}}",
"editing": "Modifica",
"editingLabel_many": "Modificare {{count}} {{label}}",
"editingLabel_one": "Modifica {{count}} {{label}}",
"editingLabel_other": "Modificare {{count}} {{label}}",
"email": "Email",
"emailAddress": "Indirizzo Email",
"enterAValue": "Inserisci un valore",
@@ -199,7 +218,9 @@
"save": "Salva",
"saving": "Salvo...",
"searchBy": "Cerca per {{label}}",
"selectAll": "Seleziona tutto {{count}} {{label}}",
"selectValue": "Seleziona un valore",
"selectedCount": "{{count}} {{label}} selezionato",
"sorryNotFound": "Siamo spiacenti, non c'è nulla che corrisponda alla tua richiesta.",
"sort": "Ordina",
"stayOnThisPage": "Rimani su questa pagina",
@@ -213,6 +234,7 @@
"unsavedChangesDuplicate": "Sono presenti modifiche non salvate. Vuoi continuare a duplicare?",
"untitled": "Senza titolo",
"updatedAt": "Aggiornato il",
"updatedCountSuccessfully": "{{count}} {{label}} aggiornato con successo.",
"updatedSuccessfully": "Aggiornato con successo.",
"updating": "Aggiornamento",
"uploading": "Caricamento",
@@ -221,20 +243,21 @@
"welcome": "Benvenuto"
},
"operators": {
"contains": "contiene",
"equals": "uguale",
"isNotEqualTo": "non è uguale a",
"isIn": "è in",
"isNotIn": "non è in",
"exists": "esiste",
"isGreaterThan": "è maggiore di",
"isGreaterThanOrEqualTo": "è maggiore o uguale a",
"isIn": "è in",
"isLessThan": "è minore di",
"isLessThanOrEqualTo": "è minore o uguale a",
"isGreaterThanOrEqualTo": "è maggiore o uguale a",
"near": "vicino",
"isLike": "è come",
"contains": "contiene"
"isNotEqualTo": "non è uguale a",
"isNotIn": "non è in",
"near": "vicino"
},
"upload": {
"dragAndDrop": "Trascina e rilascia un file",
"dragAndDropHere": "oppure trascina e rilascia un file qui",
"fileName": "Nome File",
"fileSize": "Dimensione File",
@@ -243,7 +266,6 @@
"moreInfo": "Più info",
"selectCollectionToBrowse": "Seleziona una Collezione da Sfogliare",
"selectFile": "Seleziona un file",
"dragAndDrop": "Trascina e rilascia un file",
"sizes": "Formati",
"width": "Larghezza"
},
@@ -267,15 +289,18 @@
"validUploadID": "'Questo campo non è un ID di Upload valido.'"
},
"version": {
"aboutToPublishSelection": "Stai per pubblicare tutte le {{label}} nella selezione. Sei sicuro?",
"aboutToRestore": "Stai per ripristinare questo documento {{label}} allo stato in cui si trovava il {{versionDate}}.",
"aboutToRestoreGlobal": "Stai per ripristinare {{label}} allo stato in cui si trovava il {{versionDate}}.",
"aboutToRevertToPublished": "Stai per ripristinare le modifiche di questo documento al suo stato pubblicato. Sei sicuro?",
"aboutToUnpublish": "Stai per annullare la pubblicazione di questo documento. Sei sicuro?",
"aboutToUnpublishSelection": "Stai per annullare la pubblicazione di tutte le {{label}} nella selezione. Sei sicuro?",
"autosave": "Salvataggio automatico",
"autosavedSuccessfully": "Salvataggio automatico riuscito.",
"autosavedVersion": "Versione salvata automaticamente",
"changed": "Modificato",
"compareVersion": "Confronta versione con:",
"confirmPublish": "Conferma la pubblicazione",
"confirmRevertToSaved": "Conferma il ripristino dei salvataggi",
"confirmUnpublish": "Conferma annullamento della pubblicazione",
"confirmVersionRestoration": "Conferma il ripristino della versione",
@@ -287,6 +312,7 @@
"noRowsFound": "Nessun {{label}} trovato",
"preview": "Anteprima",
"problemRestoringVersion": "Si è verificato un problema durante il ripristino di questa versione",
"publish": "Pubblicare",
"publishChanges": "Pubblica modifiche",
"published": "Pubblicato",
"restoreThisVersion": "Ripristina questa versione",
@@ -297,8 +323,8 @@
"saveDraft": "Salva Bozza",
"selectLocales": "Seleziona le lingue da visualizzare",
"selectVersionToCompare": "Seleziona una versione da confrontare",
"showingVersionsFor": "Mostra le versioni per:",
"showLocales": "Mostra localizzazioni:",
"showingVersionsFor": "Mostra le versioni per:",
"status": "Stato",
"type": "Tipo",
"unpublish": "Annulla pubblicazione",

View File

@@ -60,6 +60,7 @@
"accountAlreadyActivated": "このアカウントはすでに有効です。",
"autosaving": "このデータを自動保存する際に問題が発生しました。",
"correctInvalidFields": "無効なフィールドを修正してください。",
"deletingFile": "ファイルの削除中にエラーが発生しました。",
"deletingTitle": "{{title}} を削除する際にエラーが発生しました。接続を確認してからもう一度お試しください。",
"emailOrPasswordIncorrect": "メールアドレス、または、パスワードが正しくありません。",
"followingFieldsInvalid_many": "次のフィールドは無効です:",
@@ -81,6 +82,8 @@
"problemUploadingFile": "ファイルのアップロード中に問題が発生しました。",
"tokenInvalidOrExpired": "トークンが無効、または、有効期限が切れています。",
"unPublishingDocument": "このデータを非公開する際に問題が発生しました。",
"unableToDeleteCount": "{{total}} {{label}} から {{count}} を削除できません。",
"unableToUpdateCount": "{{total}} {{label}} のうち {{count}} 個を更新できません。",
"unauthorized": "認証されていません。このリクエストを行うにはログインが必要です。",
"unknown": "不明なエラーが発生しました。",
"unspecific": "エラーが発生しました。",
@@ -89,27 +92,34 @@
"verificationTokenInvalid": "認証トークンが無効です。"
},
"fields": {
"block": "ブロック",
"blocks": "ブロック",
"addLabel": "{{label}} を追加",
"addLink": "リンクを追加",
"addNew": "新規追加",
"addNewLabel": "{{label}} を新規追加",
"addRelationship": "リレーションシップを追加",
"addUpload": "アップロードを追加",
"block": "ブロック",
"blockType": "ブロックタイプ",
"blocks": "ブロック",
"chooseBetweenCustomTextOrDocument": "",
"chooseDocumentToLink": "",
"chooseFromExisting": "既存から選択",
"chooseLabel": "{{label}} を選択",
"collapseAll": "すべて閉じる",
"customURL": "カスタムURL",
"editLabelData": "{{label}} データを編集",
"editLink": "リンクを編集",
"editRelationship": "リレーションシップを編集",
"enterURL": "URL を入力してください",
"internalLink": "内部リンク",
"itemsAndMore": "{{items}} 他{{count}}件",
"labelRelationship": "{{label}} リレーションシップ",
"latitude": "緯度",
"linkType": "リンクタイプ",
"linkedTo": "<0>{{label}}</0> にリンク",
"longitude": "経度",
"newLabel": "新規 {{label}}",
"openInNewTab": "新しいタブで開く",
"passwordsDoNotMatch": "パスワードが一致しません",
"relatedDocument": "リレーションデータ",
"relationTo": "リレーション",
@@ -118,9 +128,11 @@
"saveChanges": "変更を保存",
"searchForBlock": "ブロックを検索",
"selectExistingLabel": "既存 {{label}} を選択",
"selectFieldsToEdit": "編集するフィールドを選択",
"showAll": "すべて開く",
"swapRelationship": "スワップ関係",
"swapUpload": "差し替え",
"textToDisplay": "",
"toggleBlock": "ブロックを切り替え",
"uploadNewLabel": "新規 {{label}} アップロード"
},

View File

@@ -60,6 +60,7 @@
"accountAlreadyActivated": "ဤအကောင့်ကို အသက်သွင်းပြီးဖြစ်သည်။",
"autosaving": "ဖိုင်ကို အလိုအလျောက်သိမ်းဆည်းရာတွင် ပြဿနာတစ်ခုရှိနေသည်။",
"correctInvalidFields": "ကျေးဇူးပြု၍ အချက်အလက်များကို ပြန်လည် စစ်ဆေးပါ။",
"deletingFile": "ဖိုင်ကိုဖျက်ရာတွင် အမှားအယွင်းရှိနေသည်။",
"deletingTitle": "{{title}} ကို ဖျက်ရာတွင် အမှားအယွင်းရှိခဲ့သည်။ သင့် အင်တာနက်လိုင်းအား စစ်ဆေးပြီး ထပ်မံကြို့စားကြည့်ပါ။",
"emailOrPasswordIncorrect": "ထည့်သွင်းထားသော အီးမေးလ် သို့မဟုတ် စကားဝှက်သည် မမှန်ပါ။",
"followingFieldsInvalid_many": "ထည့်သွင်းထားသော အချက်အလက်များသည် မမှန်ကန်ပါ။",
@@ -81,6 +82,8 @@
"problemUploadingFile": "ဖိုင်ကို အပ်လုဒ်တင်ရာတွင် ပြဿနာရှိနေသည်။",
"tokenInvalidOrExpired": "တိုကင်သည် မမှန်ကန်ပါ သို့မဟုတ် သက်တမ်းကုန်သွားပါပြီ။",
"unPublishingDocument": "ဖိုင်ကို ပြန်လည့် သိမ်းဆည်းခြင်းမှာ ပြဿနာရှိနေသည်။",
"unableToDeleteCount": "{{total}} {{label}} မှ {{count}} ကို ဖျက်၍မရပါ။",
"unableToUpdateCount": "{{total}} {{label}} မှ {{count}} ကို အပ်ဒိတ်လုပ်၍မရပါ။",
"unauthorized": "အခွင့်မရှိပါ။ ဤတောင်းဆိုချက်ကို လုပ်ဆောင်နိုင်ရန် သင်သည် လော့ဂ်အင်ဝင်ရပါမည်။",
"unknown": "ဘာမှန်းမသိသော error တက်သွားပါသည်။",
"unspecific": "Error တက်နေပါသည်။",
@@ -98,18 +101,25 @@
"block": "ဘလောက်",
"blockType": "ဘလောက် အမျိုးအစား",
"blocks": "ဘလောက်များ",
"chooseBetweenCustomTextOrDocument": "စိတ်ကြိုက်စာသား URL ကိုထည့်ခြင်း သို့မဟုတ် အခြားစာရွက်စာတမ်းတစ်ခုသို့ လင့်ခ်ချိတ်ခြင်းအကြား ရွေးချယ်ပါ။",
"chooseDocumentToLink": "ချိတ်ဆက်ရန် စာရွက်စာတမ်းကို ရွေးပါ။",
"chooseFromExisting": "ရှိပြီးသားထဲကပဲ ရွေးချယ်ပါ။",
"chooseLabel": "{{label}} အားရွေးချယ်ပါ။",
"collapseAll": "အားလုံးကို ခေါက်သိမ်းပါ။",
"customURL": "စိတ်ကြိုက် URL",
"editLabelData": "ဒေတာ {{label}} ကို တည်းဖြတ်ပါ။",
"editLink": "လင့်ခ်ကို တည်းဖြတ်ပါ။",
"editRelationship": "Relationship ကို တည်းဖြတ်ပါ။",
"enterURL": "URL တစ်ခုထည့်ပါ။",
"internalLink": "Internal Link",
"itemsAndMore": "{{items}} နှင့် နောက်ထပ် {{count}} ခု",
"labelRelationship": "{{label}} Relationship",
"latitude": "vĩ độ",
"linkType": "လင့်အမျိုးအစား",
"linkedTo": "<0>{{label}}</0> ချိတ်ဆက်ထားသည်။",
"longitude": "kinh độ",
"newLabel": "{{label}} အသစ်",
"openInNewTab": "တက်ဘ်အသစ်တွင် ဖွင့်ပါ။",
"passwordsDoNotMatch": "စကားဝှက်များနှင့် မကိုက်ညီပါ။",
"relatedDocument": "ဆက်စပ် ဖိုင်",
"relationTo": "ဆက်စပ်မှု",
@@ -118,18 +128,24 @@
"saveChanges": "သိမ်းဆည်းမည်။",
"searchForBlock": "ဘလောက်တစ်ခုရှာမည်။",
"selectExistingLabel": "ရှိပြီးသား {{label}} ကို ရွေးပါ",
"selectFieldsToEdit": "တည်းဖြတ်ရန် အကွက်များကို ရွေးပါ။",
"showAll": "အကုန် ကြည့်မည်။",
"swapRelationship": "လဲလှယ်ဆက်ဆံရေး",
"swapUpload": "အပ်လုဒ်ဖလှယ်ပါ။",
"textToDisplay": "ပြသရန် စာသား",
"toggleBlock": "Toggle block",
"uploadNewLabel": "{{label}} အသစ်တင်မည်။"
},
"general": {
"aboutToDelete": "{{label}} <1>{{title}}</1> ကို ဖျက်ပါတော့မည်။ သေချာပြီလား။ ဖျက်ပြီးရင် ပြန်မရဘူးနော်။",
"aboutToDeleteCount_many": "သင်သည် {{count}} {{label}} ကို ဖျက်ပါတော့မည်။",
"aboutToDeleteCount_one": "သင်သည် {{count}} {{label}} ကို ဖျက်ပါတော့မည်။",
"aboutToDeleteCount_other": "သင်သည် {{count}} {{label}} ကို ဖျက်ပါတော့မည်။",
"addBelow": "အောက်တွင်ထည့်ပါ။",
"addFilter": "ဇကာထည့်ပါ။",
"adminTheme": "Admin Theme",
"and": "နှင့်",
"ascending": "တက်နေသည်",
"automatic": "အော်တို",
"backToDashboard": "ပင်မစာမျက်နှာသို့ ပြန်သွားမည်။",
"cancel": "မလုပ်တော့ပါ။",
@@ -152,6 +168,7 @@
"dark": "အမှောင်",
"dashboard": "ပင်မစာမျက်နှာ",
"delete": "ဖျက်မည်။",
"deletedCountSuccessfully": "{{count}} {{label}} ကို အောင်မြင်စွာ ဖျက်လိုက်ပါပြီ။",
"deletedSuccessfully": "အောင်မြင်စွာ ဖျက်လိုက်ပါပြီ။",
"deleting": "ဖျက်နေဆဲ ...",
"descending": "Descending",
@@ -160,6 +177,9 @@
"edit": "တည်းဖြတ်ပါ။",
"editLabel": "{{label}} ပြင်ဆင်မည်။",
"editing": "ပြင်ဆင်နေသည်။",
"editingLabel_many": "တည်းဖြတ်ခြင်း {{count}} {{label}}",
"editingLabel_one": "တည်းဖြတ်ခြင်း {{count}} {{label}}",
"editingLabel_other": "တည်းဖြတ်ခြင်း {{count}} {{label}}",
"email": "အီးမေးလ်",
"emailAddress": "အီးမေးလ် လိပ်စာ",
"enterAValue": "တန်ဖိုးတစ်ခုထည့်ပါ။",
@@ -198,7 +218,9 @@
"save": "သိမ်းဆည်းမည်။",
"saving": "သိမ်းနေဆဲ ...",
"searchBy": "ရှာဖွေပါ။",
"selectAll": "{{count}} {{label}} အားလုံးကို ရွေးပါ",
"selectValue": "တစ်ခုခုကို ရွေးချယ်ပါ။",
"selectedCount": "{{count}} {{label}} ကို ရွေးထားသည်။",
"sorryNotFound": "ဝမ်းနည်းပါသည်။ သင်ရှာနေတဲ့ဟာ ဒီမှာမရှိပါ။",
"sort": "အစဉ်လိုက်",
"stayOnThisPage": "ဒီမှာပဲ ဆက်နေမည်။",
@@ -212,6 +234,7 @@
"unsavedChangesDuplicate": "သင့်တွင် မသိမ်းဆည်းရသေးသော ပြောင်းလဲမှုများ ရှိနေပါသည်။ ပုံတူပွားမှာ သေချာပြီလား။",
"untitled": "ခေါင်းစဥ်မဲ့",
"updatedAt": "ပြင်ဆင်ခဲ့သည့်အချိန်",
"updatedCountSuccessfully": "{{count}} {{label}} ကို အောင်မြင်စွာ အပ်ဒိတ်လုပ်ခဲ့သည်။",
"updatedSuccessfully": "အပ်ဒိတ်လုပ်ပြီးပါပြီ။",
"updating": "ပြင်ဆင်ရန်",
"uploading": "တင်ပေးနေသည်",
@@ -220,20 +243,21 @@
"welcome": "ကြိုဆိုပါတယ်။"
},
"operators": {
"contains": "ပါဝင်သည်",
"equals": "ညီမျှ",
"isNotEqualTo": "ညီမျှသည်",
"isIn": "ရှိ",
"isNotIn": "မဝင်ပါ",
"exists": "တည်ရှိသည်",
"isGreaterThan": "ထက်ကြီးသည်",
"isGreaterThanOrEqualTo": "ထက်ကြီးသည် သို့မဟုတ် ညီမျှသည်",
"isIn": "ရှိ",
"isLessThan": "ထက်နည်းသည်",
"isLessThanOrEqualTo": "ထက်နည်းသည် သို့မဟုတ် ညီမျှသည်",
"isGreaterThanOrEqualTo": "ထက်ကြီးသည် သို့မဟုတ် ညီမျှသည်",
"near": "နီး",
"isLike": "တူသည်",
"contains": "ပါဝင်သည်"
"isNotEqualTo": "ညီမျှသည်",
"isNotIn": "မဝင်ပါ",
"near": "နီး"
},
"upload": {
"dragAndDrop": "ဖိုင်တစ်ဖိုင်ကို ဆွဲချလိုက်ပါ။",
"dragAndDropHere": "သို့မဟုတ် ဖိုင်တစ်ခုကို ဤနေရာတွင် ဆွဲချပါ။",
"fileName": "ဖိုင် နာမည်",
"fileSize": "ဖိုင် အရွယ်အစား",
@@ -242,14 +266,13 @@
"moreInfo": "More info",
"selectCollectionToBrowse": "စုစည်းမှု တစ်ခုခုကို ရွေးချယ်ပါ။",
"selectFile": "ဖိုင်ရွေးပါ။",
"dragAndDrop": "ဖိုင်တစ်ဖိုင်ကို ဆွဲချလိုက်ပါ။",
"sizes": "အရွယ်အစားများ",
"width": "အကျယ်"
},
"validation": {
"fieldHasNo": "ဤအကွက်တွင် {{label}} မရှိပါ။",
"emailAddress": "မှန်ကန်သော အီးမေးလ်လိပ်စာကို ထည့်သွင်းပါ။",
"enterNumber": "မှန်ကန်သောနံပါတ်တစ်ခုထည့်ပါ။",
"fieldHasNo": "ဤအကွက်တွင် {{label}} မရှိပါ။",
"greaterThanMax": "\"{{value}}\" သည် {{max}} ၏ အများဆုံးခွင့်ပြုထားသော တန်ဖိုးထက် ကြီးသည်။",
"invalidInput": "ဤအကွက်တွင် မမှန်ကန်သော ထည့်သွင်းမှုတစ်ခုရှိသည်။",
"invalidSelection": "ဤအကွက်တွင် မမှန်ကန်သော ရွေးချယ်မှုတစ်ခုရှိသည်။",
@@ -266,15 +289,18 @@
"validUploadID": "'ဤအကွက်သည် မှန်ကန်သော အပ်လုဒ် ID မဟုတ်ပါ။'"
},
"version": {
"aboutToPublishSelection": "သင်သည် ရွေးချယ်မှုတွင် {{label}} အားလုံးကို ထုတ်ဝေပါတော့မည်။ သေချာလား?",
"aboutToRestore": "သင်သည် ဤ {{label}} စာရွက်စာတမ်းကို {{versionDate}} တွင် ပါရှိသည့် အခြေအနေသို့ ပြန်ယူတော့မည်။",
"aboutToRestoreGlobal": "သင်သည် ဂလိုဘယ် {{label}} ကို {{versionDate}} တွင် ပါရှိသည့် အခြေအနေသို့ ပြန်လည်ရောက်ရှိတော့မည်ဖြစ်သည်။",
"aboutToRevertToPublished": "သင်သည် အပြောင်းအလဲများကို အများဆိုင် အခြေအနေသို့ ပြန်ပြောင်းပါတော့မည်။ သေချာလား?",
"aboutToUnpublish": "အများဆိုင်မှ ပြန်ဖြုတ်တော့မည်။ သေချာလား",
"aboutToUnpublishSelection": "သင်သည် ရွေးချယ်မှုတွင် {{label}} အားလုံးကို ထုတ်ဝေတော့မည် ဖြစ်သည်။ သေချာလား?",
"autosave": "အလိုအလျောက်သိမ်းဆည်းပါ။",
"autosavedSuccessfully": "အလိုအလျောက် သိမ်းဆည်းပြီးပါပြီ။",
"autosavedVersion": "အော်တို ဗားရှင်း",
"changed": "ပြောင်းခဲ့သည်။",
"compareVersion": "ဗားရှင်းနှင့် နှိုင်းယှဉ်ချက်:",
"confirmPublish": "ထုတ်ဝေအတည်ပြုပါ။",
"confirmRevertToSaved": "သိမ်းဆည်းပြီးကြောင်း အတည်ပြုပါ။",
"confirmUnpublish": "အများဆိုင်ကို ဖျက်ရန် အတည်ပြုပါ။",
"confirmVersionRestoration": "ဗားရှင်းပြန်လည် အသုံးပြုခြင်းကို အတည်ပြုပါ။",
@@ -286,6 +312,7 @@
"noRowsFound": "{{label}} အားမတွေ့ပါ။",
"preview": "နမူနာပြရန်",
"problemRestoringVersion": "ဤဗားရှင်းကို ပြန်လည်ရယူရာတွင် ပြဿနာရှိနေသည်။",
"publish": "ထုတ်ဝေသည်။",
"publishChanges": "အပြောင်းအလဲများကို တင်ခဲ့သည်။",
"published": "တင်ပြီးပြီ။",
"restoreThisVersion": "ဤဗားရှင်းကိုကို ပြန်ယူမည်။",
@@ -297,6 +324,7 @@
"selectLocales": "ပြသရန် ဒေသန္တရများကို ရွေးပါ။",
"selectVersionToCompare": "နှိုင်းယှဉ်ရန် ဗားရှင်းကို ရွေးပါ။",
"showLocales": "ဒေသန္တရများကိုပြပါ။:",
"showingVersionsFor": "အတွက် ဗားရှင်းများကို ပြသနေသည်-",
"status": "အခြေအနေ",
"type": "အမျိုးအစား",
"unpublish": "ပြန်ဖြုတ်မည်။",
@@ -305,6 +333,7 @@
"versionCount_many": "{{count}} ဗားရှင်းများကို တွေ့ပါသည်။",
"versionCount_none": "ဗားရှင်းရှာဖွေ့ပါ။",
"versionCount_one": "{{count}} ဗားရှင်အား တွေ့ပါသည်။",
"versionCount_other": "ဗားရှင်း {{count}} ခု တွေ့ရှိပါသည်။",
"versionCreatedOn": "{{version}} အား ဖန်တီးခဲ့သည်။",
"versionID": "ဗားရှင်း ID",
"versions": "ဗားရှင်းများ",

View File

@@ -82,6 +82,8 @@
"problemUploadingFile": "Det oppstod et problem under opplasting av filen.",
"tokenInvalidOrExpired": "Token er enten ugyldig eller har utløpt.",
"unPublishingDocument": "Det oppstod et problem under avpublisering av dokumentet.",
"unableToDeleteCount": "Kan ikke slette {{count}} av {{total}} {{label}}.",
"unableToUpdateCount": "Kan ikke oppdatere {{count}} av {{total}} {{label}}.",
"unauthorized": "Uautorisert, du må være innlogget for å gjøre denne forespørselen.",
"unknown": "En ukjent feil har oppstått.",
"unspecific": "En feil har oppstått.",
@@ -126,6 +128,7 @@
"saveChanges": "Lagre endringer",
"searchForBlock": "Søk etter en blokk",
"selectExistingLabel": "Velg eksisterende {{label}}",
"selectFieldsToEdit": "Velg felt som skal redigeres",
"showAll": "Vis alle",
"swapRelationship": "Bytte Forhold",
"swapUpload": "Bytt Opplasting",
@@ -135,10 +138,14 @@
},
"general": {
"aboutToDelete": "Du er i ferd med å slette {{label}} <1>{{title}}</1>. Er du sikker?",
"aboutToDeleteCount_many": "Du er i ferd med å slette {{count}} {{label}}",
"aboutToDeleteCount_one": "Du er i ferd med å slette {{count}} {{label}}",
"aboutToDeleteCount_other": "Du er i ferd med å slette {{count}} {{label}}",
"addBelow": "Legg til under",
"addFilter": "Legg til filter",
"adminTheme": "Admin-tema",
"and": "Og",
"ascending": "Stigende",
"automatic": "Automatisk",
"backToDashboard": "Tilbake til kontrollpanel",
"cancel": "Avbryt",
@@ -161,6 +168,7 @@
"dark": "Mørk",
"dashboard": "Kontrollpanel",
"delete": "Slett",
"deletedCountSuccessfully": "Slettet {{count}} {{label}}.",
"deletedSuccessfully": "Slettet.",
"deleting": "Sletter...",
"descending": "Synkende",
@@ -169,6 +177,9 @@
"edit": "Redigere",
"editLabel": "Rediger {{label}}",
"editing": "Redigerer",
"editingLabel_many": "Redigerer {{count}} {{label}}",
"editingLabel_one": "Redigerer {{count}} {{label}}",
"editingLabel_other": "Redigerer {{count}} {{label}}",
"email": "E-post",
"emailAddress": "E-postadresse",
"enterAValue": "Skriv inn en verdi",
@@ -207,7 +218,9 @@
"save": "Lagre",
"saving": "Lagrer...",
"searchBy": "Søk etter {{label}}",
"selectAll": "Velg alle {{count}} {{label}}",
"selectValue": "Velg en verdi",
"selectedCount": "{{count}} {{label}} valgt",
"sorryNotFound": "Beklager, det er ingenting som samsvarer med forespørselen din.",
"sort": "Sortér",
"stayOnThisPage": "Bli på denne siden",
@@ -221,6 +234,7 @@
"unsavedChangesDuplicate": "Du har ulagrede endringer. Vil du fortsette å duplisere?",
"untitled": "Uten tittel",
"updatedAt": "Oppdatert",
"updatedCountSuccessfully": "Oppdaterte {{count}} {{label}} vellykket.",
"updatedSuccessfully": "Oppdatert.",
"updating": "Oppdatering",
"uploading": "Opplasting",
@@ -229,20 +243,21 @@
"welcome": "Velkommen"
},
"operators": {
"contains": "contains",
"equals": "lik",
"isNotEqualTo": "er ikke lik",
"isIn": "er i",
"isNotIn": "er ikke med",
"exists": "eksisterer",
"isGreaterThan": "er større enn",
"isGreaterThanOrEqualTo": "er større enn eller lik",
"isIn": "er i",
"isLessThan": "er mindre enn",
"isLessThanOrEqualTo": "er mindre enn eller lik",
"isGreaterThanOrEqualTo": "er større enn eller lik",
"near": "nær",
"isLike": "er som",
"contains": "contains"
"isNotEqualTo": "er ikke lik",
"isNotIn": "er ikke med",
"near": "nær"
},
"upload": {
"dragAndDrop": "Dra og slipp en fil",
"dragAndDropHere": "eller dra og slipp en fil her",
"fileName": "Filnavn",
"fileSize": "Filstørrelse",
@@ -251,7 +266,6 @@
"moreInfo": "Mer info",
"selectCollectionToBrowse": "Velg en samling å bla i",
"selectFile": "Velg en fil",
"dragAndDrop": "Dra og slipp en fil",
"sizes": "Størrelser",
"width": "Bredde"
},
@@ -275,15 +289,18 @@
"validUploadID": "Dette feltet er ikke en gyldig opplastings-ID."
},
"version": {
"aboutToPublishSelection": "Du er i ferd med å publisere alle {{label}} i utvalget. Er du sikker?",
"aboutToRestore": "Du er i ferd med å gjenopprette denne {{label}} dokumentet til tilstanden det var i på {{versionDate}}.",
"aboutToRestoreGlobal": "Du er i ferd med å gjenopprette den globale variabelen {{label}} til tilstanden det var i på {{versionDate}}.",
"aboutToRevertToPublished": "Du er i ferd med å tilbakestille endringene i dette dokumentet til den publiserte tilstanden. Er du sikker?",
"aboutToUnpublish": "Du er i ferd med å avpublisere dette dokumentet. Er du sikker?",
"aboutToUnpublishSelection": "Du er i ferd med å oppheve publiseringen av alle {{label}} i utvalget. Er du sikker?",
"autosave": "Lagre automatisk",
"autosavedSuccessfully": "Lagret automatisk.",
"autosavedVersion": "Automatisk lagret versjon",
"changed": "Endret",
"compareVersion": "Sammenlign versjon mot:",
"confirmPublish": "Bekreft publisering",
"confirmRevertToSaved": "Bekreft tilbakestilling til lagret",
"confirmUnpublish": "Bekreft avpublisering",
"confirmVersionRestoration": "Bekreft versjon-gjenoppretting",
@@ -295,6 +312,7 @@
"noRowsFound": "Ingen {{label}} funnet",
"preview": "Forhåndsvisning",
"problemRestoringVersion": "Det oppstod et problem med gjenoppretting av denne versjonen",
"publish": "Publisere",
"publishChanges": "Publiser endringer",
"published": "Publisert",
"restoreThisVersion": "Gjenopprett denne versjonen",
@@ -305,8 +323,8 @@
"saveDraft": "Lagre utkast",
"selectLocales": "Velg språk å vise",
"selectVersionToCompare": "Velg en versjon å sammenligne",
"showingVersionsFor": "Viser versjoner for:",
"showLocales": "Vis språk:",
"showingVersionsFor": "Viser versjoner for:",
"status": "Status",
"type": "Type",
"unpublish": "Avpubliser",

View File

@@ -82,6 +82,8 @@
"problemUploadingFile": "Er was een probleem bij het uploaden van het bestand.",
"tokenInvalidOrExpired": "Token is ongeldig of verlopen.",
"unPublishingDocument": "Er was een probleem met het depubliceren van dit document.",
"unableToDeleteCount": "Kan {{count}} van {{total}} {{label}} niet verwijderen.",
"unableToUpdateCount": "Kan {{count}} van {{total}} {{label}} niet updaten.",
"unauthorized": "Ongeautoriseerd, u moet ingelogd zijn om dit verzoek te doen.",
"unknown": "Er is een onbekende fout opgetreden.",
"unspecific": "Er is een fout opgetreden.",
@@ -90,27 +92,34 @@
"verificationTokenInvalid": "Verificatietoken is ongeldig."
},
"fields": {
"block": "blok",
"blocks": "blokken",
"addLabel": "Voeg {{label}} toe",
"addLink": "Voeg een link toe",
"addNew": "Nieuw(e)",
"addNewLabel": "Nieuw(e) {{label}} toevoegen",
"addRelationship": "Nieuwe Relatie",
"addUpload": "Upload Toevoegen",
"block": "blok",
"blockType": "Bloktype",
"blocks": "blokken",
"chooseBetweenCustomTextOrDocument": "Kies tussen het invoeren van een aangepaste tekst-URL of een koppeling naar een ander document.",
"chooseDocumentToLink": "Kies een document om naar te linken",
"chooseFromExisting": "Kies uit bestaande",
"chooseLabel": "Kies {{label}}",
"collapseAll": "Alles samenvouwen",
"customURL": "Eigen URL",
"editLabelData": "Bewerk gegevens van {{label}}",
"editLink": "Link bewerken",
"editRelationship": "Relatie Relatie",
"enterURL": "Voer een URL in",
"internalLink": "Interne koppeling",
"itemsAndMore": "{{items}} en {{count}} meer",
"labelRelationship": "{{label}} relatie",
"latitude": "Breedtegraad",
"linkType": "Koppelingstype",
"linkedTo": "Gekoppeld aan aan <0>{{label}}</0>",
"longitude": "Lengtegraad",
"newLabel": "Nieuw(e) {{label}}",
"openInNewTab": "Openen in nieuw tabblad",
"passwordsDoNotMatch": "Wachtwoorden komen niet overeen.",
"relatedDocument": "Gerelateerd document",
"relationTo": "Relatie tot",
@@ -119,18 +128,24 @@
"saveChanges": "Bewaar aanpassingen",
"searchForBlock": "Zoeken naar een blok",
"selectExistingLabel": "Selecteer bestaand(e) {{label}}",
"selectFieldsToEdit": "Selecteer velden om te bewerken",
"showAll": "Alles tonen",
"swapRelationship": "Relatie Wisselen",
"swapUpload": "Upload Verwisselen",
"textToDisplay": "Tekst om weer te geven",
"toggleBlock": "Blok togglen",
"uploadNewLabel": "Upload nieuw(e) {{label}}"
},
"general": {
"aboutToDelete": "U staat op het punt om {{label}} <1>{{title}}</1> te verwijderen. Weet u het zeker?",
"aboutToDeleteCount_many": "Je staat op het punt {{count}} {{label}} te verwijderen",
"aboutToDeleteCount_one": "Je staat op het punt {{count}} {{label}} te verwijderen",
"aboutToDeleteCount_other": "Je staat op het punt {{count}} {{label}} te verwijderen",
"addBelow": "Onderaan toevoegen",
"addFilter": "Filter toevoegen",
"adminTheme": "Adminthema",
"and": "En",
"ascending": "Oplopend",
"automatic": "Automatisch",
"backToDashboard": "Terug naar dashboard",
"cancel": "Annuleren",
@@ -153,6 +168,7 @@
"dark": "Donker",
"dashboard": "Dashboard",
"delete": "Verwijderen",
"deletedCountSuccessfully": "{{count}} {{label}} succesvol verwijderd.",
"deletedSuccessfully": "Succesvol verwijderd.",
"deleting": "Verwijderen...",
"descending": "Aflopend",
@@ -161,6 +177,9 @@
"edit": "Bewerk",
"editLabel": "Bewerk {{label}}",
"editing": "Bewerken",
"editingLabel_many": "Bewerken {{count}} {{label}}",
"editingLabel_one": "Bewerken {{count}} {{label}}",
"editingLabel_other": "Bewerken {{count}} {{label}}",
"email": "E-mail",
"emailAddress": "E-maildres",
"enterAValue": "Waarde invoeren",
@@ -199,7 +218,9 @@
"save": "Bewaar",
"saving": "Bewaren...",
"searchBy": "Zoeken op {{label}}",
"selectAll": "Alles selecteren {{count}} {{label}}",
"selectValue": "Selecteer een waarde",
"selectedCount": "{{count}} {{label}} geselecteerd",
"sorryNotFound": "Sorry, er is niets dat overeen komt met uw verzoek.",
"sort": "Sorteer",
"stayOnThisPage": "Blijf op deze pagina",
@@ -213,6 +234,7 @@
"unsavedChangesDuplicate": "U heeft onbewaarde wijzigingen. Wilt u doorgaan met dupliceren?",
"untitled": "Zonder titel",
"updatedAt": "Aangepast op",
"updatedCountSuccessfully": "{{count}} {{label}} succesvol bijgewerkt.",
"updatedSuccessfully": "Succesvol aangepast.",
"updating": "Bijwerken",
"uploading": "Uploaden",
@@ -221,20 +243,21 @@
"welcome": "Welkom"
},
"operators": {
"contains": "bevat",
"equals": "is gelijk aan",
"isNotEqualTo": "is niet gelijk aan",
"isIn": "is binnen",
"isNotIn": "zit er niet in",
"exists": "bestaat",
"isGreaterThan": "is groter dan",
"isGreaterThanOrEqualTo": "is groter dan of gelijk aan",
"isIn": "is binnen",
"isLessThan": "is kleiner dan",
"isLessThanOrEqualTo": "is kleiner dan of gelijk aan",
"isGreaterThanOrEqualTo": "is groter dan of gelijk aan",
"near": "nabij",
"isLike": "is als",
"contains": "bevat"
"isNotEqualTo": "is niet gelijk aan",
"isNotIn": "zit er niet in",
"near": "nabij"
},
"upload": {
"dragAndDrop": "Sleep een bestand",
"dragAndDropHere": "of sleep een bestand naar hier",
"fileName": "Bestandsnaam",
"fileSize": "Bestandsgrootte",
@@ -243,7 +266,6 @@
"moreInfo": "Meer info",
"selectCollectionToBrowse": "Selecteer een collectie om door te bladeren",
"selectFile": "Selecteer een bestand",
"dragAndDrop": "Sleep een bestand",
"sizes": "Groottes",
"width": "Breedte"
},
@@ -267,15 +289,18 @@
"validUploadID": "Dit veld is geen geldige upload-ID."
},
"version": {
"aboutToPublishSelection": "Je staat op het punt om alle {{label}} in de selectie te publiceren. Weet je het zeker?",
"aboutToRestore": "U staat op het punt dit {{label}} document te herstellen in de staat waarin het zich bevond op {{versionDate}}.",
"aboutToRestoreGlobal": "U staat op het punt om de global {{label}} te herstellen in de staat waarin het zich bevond op {{versionDate}}.",
"aboutToRevertToPublished": "U staat op het punt om de wijzigingen van dit document terug te draaien naar de gepubliceerde staat. Weet u het zeker?",
"aboutToUnpublish": "U staat op het punt om de publicatie van dit document ongedaan te maken. Weet u het zeker?",
"aboutToUnpublishSelection": "You are about to unpublish all {{label}} in the selection. Are you sure?",
"autosave": "Automatisch bewaren",
"autosavedSuccessfully": "Succesvol automatisch bewaard.",
"autosavedVersion": "Automatisch bewaarde versie",
"changed": "Gewijzigd",
"compareVersion": "Vergelijk versie met:",
"confirmPublish": "Bevestig publiceren",
"confirmRevertToSaved": "Bevestig terugdraaien naar bewaarde versie",
"confirmUnpublish": "Bevestig depubliceren",
"confirmVersionRestoration": "Bevestig te herstellen versie",
@@ -287,6 +312,7 @@
"noRowsFound": "Geen {{label}} gevonden",
"preview": "Voorbeeld",
"problemRestoringVersion": "Er was een probleem bij het herstellen van deze versie",
"publish": "Publiceren",
"publishChanges": "Publiceer wijzigingen",
"published": "Gepubliceerd",
"restoreThisVersion": "Herstel deze versie",
@@ -298,6 +324,7 @@
"selectLocales": "Selecteer locales om weer te geven",
"selectVersionToCompare": "Selecteer een versie om te vergelijken",
"showLocales": "Toon locales:",
"showingVersionsFor": "Versies tonen voor:",
"status": "Status",
"type": "Type",
"unpublish": "Publicatie ongedaan maken",
@@ -306,6 +333,7 @@
"versionCount_many": "{{count}} versies gevonden",
"versionCount_none": "Geen versies gevonden",
"versionCount_one": "{{count}} versie gevonden",
"versionCount_other": "{{count}} versies gevonden",
"versionCreatedOn": "{{version}} aangemaakt op:",
"versionID": "Versie-ID",
"versions": "Versies",

View File

@@ -60,6 +60,7 @@
"accountAlreadyActivated": "To konto zostało już aktywowane.",
"autosaving": "Wystąpił problem podczas automatycznego zapisywania tego dokumentu.",
"correctInvalidFields": "Popraw nieprawidłowe pola.",
"deletingFile": "",
"deletingTitle": "Wystąpił błąd podczas usuwania {{title}}. Proszę, sprawdź swoje połączenie i spróbuj ponownie.",
"emailOrPasswordIncorrect": "Podany adres e-mail lub hasło jest nieprawidłowe.",
"followingFieldsInvalid_many": "Następujące pola są nieprawidłowe:",
@@ -81,6 +82,8 @@
"problemUploadingFile": "Wystąpił problem podczas przesyłania pliku.",
"tokenInvalidOrExpired": "Token jest nieprawidłowy lub wygasł.",
"unPublishingDocument": "Wystąpił problem podczas cofania publikacji tego dokumentu.",
"unableToDeleteCount": "Nie można usunąć {{count}} z {{total}} {{label}}.",
"unableToUpdateCount": "Nie można zaktualizować {{count}} z {{total}} {{label}}.",
"unauthorized": "Brak dostępu, musisz być zalogowany.",
"unknown": "Wystąpił nieznany błąd.",
"unspecific": "Wystąpił błąd",
@@ -89,27 +92,34 @@
"verificationTokenInvalid": "Token weryfikacyjny jest nieprawidłowy."
},
"fields": {
"block": "Blok",
"blocks": "Bloki",
"addLabel": "Dodaj {{label}}",
"addLink": "Dodaj Link",
"addNew": "Dodaj nowy",
"addNewLabel": "Dodaj nowy {{label}}",
"addRelationship": "Dodaj Relacje",
"addUpload": "Dodaj ładowanie",
"block": "Blok",
"blockType": "Typ Bloku",
"blocks": "Bloki",
"chooseBetweenCustomTextOrDocument": "Wybierz między wprowadzeniem niestandardowego tekstowego adresu URL a linkiem do innego dokumentu.",
"chooseDocumentToLink": "Wybierz dokument, do którego chcesz utworzyć łącze",
"chooseFromExisting": "Wybierz z istniejących",
"chooseLabel": "Wybierz {{label}}",
"collapseAll": "Zwiń wszystko",
"customURL": "Niestandardowy adres URL",
"editLabelData": "Edytuj dane {{label}}",
"editLink": "Edytuj Link",
"editRelationship": "Edytuj Relacje",
"enterURL": "Wpisz adres URL",
"internalLink": "Link wewnętrzny",
"itemsAndMore": "{{items}} i {{count}} więcej",
"labelRelationship": "Relacja {{label}}",
"latitude": "Szerokość",
"linkType": "Typ łącza",
"linkedTo": "Połączony z <0>{{etykietą}}</0>",
"longitude": "Długość geograficzna",
"newLabel": "Nowy {{label}}",
"openInNewTab": "Otwórz w nowej karcie",
"passwordsDoNotMatch": "Hasła nie pasują",
"relatedDocument": "Powiązany dokument",
"relationTo": "Powiązany z",
@@ -118,18 +128,24 @@
"saveChanges": "Zapisz zmiany",
"searchForBlock": "Szukaj bloku",
"selectExistingLabel": "Wybierz istniejący {{label}}",
"selectFieldsToEdit": "Wybierz pola do edycji",
"showAll": "Pokaż wszystkie",
"swapRelationship": "Zamiana Relacji",
"swapUpload": "Zamień Wrzucone",
"textToDisplay": "Tekst do wyświetlenia",
"toggleBlock": "Przełącz blok",
"uploadNewLabel": "Wrzuć nowy {{label}}"
},
"general": {
"aboutToDelete": "Zamierzasz usunąć {{label}} <1>{{title}}</1>. Jesteś pewien?",
"aboutToDeleteCount_many": "Zamierzasz usunąć {{count}} {{label}}",
"aboutToDeleteCount_one": "Zamierzasz usunąć {{count}} {{label}}",
"aboutToDeleteCount_other": "Zamierzasz usunąć {{count}} {{label}}",
"addBelow": "Dodaj boniżej",
"addFilter": "Dodaj filtr",
"adminTheme": "Motyw administratora",
"and": "I",
"ascending": "Rosnąco",
"automatic": "Automatyczny",
"backToDashboard": "Powrót do panelu",
"cancel": "Anuluj",
@@ -152,6 +168,7 @@
"dark": "Ciemny",
"dashboard": "Panel",
"delete": "Usuń",
"deletedCountSuccessfully": "",
"deletedSuccessfully": "Skutecznie usunięte.",
"deleting": "Usuwanie...",
"descending": "Malejąco",
@@ -160,6 +177,9 @@
"edit": "Edytować",
"editLabel": "Edytuj {{label}}",
"editing": "Edycja",
"editingLabel_many": "Edytowanie {{count}} {{label}}",
"editingLabel_one": "Edytowanie {{count}} {{label}}",
"editingLabel_other": "Edytowanie {{count}} {{label}}",
"email": "Email",
"emailAddress": "Adres email",
"enterAValue": "Wpisz wartość",
@@ -198,7 +218,9 @@
"save": "Zapisz",
"saving": "Zapisywanie...",
"searchBy": "Szukaj według",
"selectAll": "Wybierz wszystkie {{liczba}} {{etykieta}}",
"selectValue": "Wybierz wartość",
"selectedCount": "Wybrano {{count}} {{label}}",
"sorryNotFound": "Przepraszamy — nie ma nic, co odpowiadałoby twojej prośbie.",
"sort": "Sortuj",
"stayOnThisPage": "Pozostań na stronie",
@@ -212,6 +234,7 @@
"unsavedChangesDuplicate": "Masz niezapisane zmiany. Czy chcesz kontynuować duplikowanie?",
"untitled": "Bez nazwy",
"updatedAt": "Data edycji",
"updatedCountSuccessfully": "Pomyślnie zaktualizowano {{count}} {{label}}.",
"updatedSuccessfully": "Aktualizacja zakończona sukcesem.",
"updating": "Aktualizacja",
"uploading": "Wgrywanie",
@@ -220,20 +243,21 @@
"welcome": "Witaj"
},
"operators": {
"contains": "zawiera",
"equals": "równe",
"isNotEqualTo": "nie jest równe",
"isIn": "jest w",
"isNotIn": "nie ma go w",
"exists": "istnieje",
"isGreaterThan": "jest większy niż",
"isGreaterThanOrEqualTo": "jest większe lub równe",
"isIn": "jest w",
"isLessThan": "jest mniejsze niż",
"isLessThanOrEqualTo": "jest mniejsze lub równe",
"isGreaterThanOrEqualTo": "jest większe lub równe",
"near": "blisko",
"isLike": "jest jak",
"contains": "zawiera"
"isNotEqualTo": "nie jest równe",
"isNotIn": "nie ma go w",
"near": "blisko"
},
"upload": {
"dragAndDrop": "Przeciągnij i upuść plik",
"dragAndDropHere": "lub złap i upuść plik tutaj",
"fileName": "Nazwa pliku",
"fileSize": "Rozmiar pliku",
@@ -242,7 +266,6 @@
"moreInfo": "Więcej informacji",
"selectCollectionToBrowse": "Wybierz kolekcję aby przejrzeć",
"selectFile": "Wybierz plik",
"dragAndDrop": "Przeciągnij i upuść plik",
"sizes": "Rozmiary",
"width": "Szerokość"
},
@@ -266,15 +289,18 @@
"validUploadID": "To pole nie jest prawidłowym identyfikatorem przesyłania."
},
"version": {
"aboutToPublishSelection": "Za chwilę opublikujesz wszystkie {{label}} w zaznaczeniu. Jesteś pewny?",
"aboutToRestore": "Zamierzasz przywrócić dokument {{label}} do stanu, w jakim znajdował się w dniu {{versionDate}}.",
"aboutToRestoreGlobal": "Zamierzasz przywrócić globalny rekord {{label}} do stanu, w którym znajdował się w dniu {{versionDate}}.",
"aboutToRevertToPublished": "Zamierzasz przywrócić zmiany w tym dokumencie do stanu opublikowanego. Jesteś pewien?",
"aboutToUnpublish": "Zamierzasz cofnąć publikację tego dokumentu. Jesteś pewien?",
"aboutToUnpublishSelection": "Zamierzasz cofnąć publikację wszystkich {{label}} w zaznaczeniu. Jesteś pewny?",
"autosave": "Autozapis",
"autosavedSuccessfully": "Pomyślnie zapisano automatycznie.",
"autosavedVersion": "Wersja zapisana automatycznie",
"changed": "Zmieniono",
"compareVersion": "Porównaj wersję z:",
"confirmPublish": "Potwierdź publikację",
"confirmRevertToSaved": "Potwierdź powrót do zapisanego",
"confirmUnpublish": "Potwierdź cofnięcie publikacji",
"confirmVersionRestoration": "Potwierdź przywrócenie wersji",
@@ -286,6 +312,7 @@
"noRowsFound": "Nie znaleziono {{label}}",
"preview": "Podgląd",
"problemRestoringVersion": "Wystąpił problem podczas przywracania tej wersji",
"publish": "Publikować",
"publishChanges": "Opublikuj zmiany",
"published": "Opublikowano",
"restoreThisVersion": "Przywróć tę wersję",
@@ -297,6 +324,7 @@
"selectLocales": "Wybierz lokalizacje do wyświetlenia",
"selectVersionToCompare": "Wybierz wersję do porównania",
"showLocales": "Pokaż lokalizacje:",
"showingVersionsFor": "Wyświetlanie wersji dla:",
"status": "Status",
"type": "Typ",
"unpublish": "Cofnij publikację",
@@ -305,6 +333,7 @@
"versionCount_many": "Znalezionych wersji: {{count}}",
"versionCount_none": "Nie znaleziono wersji",
"versionCount_one": "Znaleziono {{count}} wersję",
"versionCount_other": "Znaleziono {{count}} wersji",
"versionCreatedOn": "Wersja {{version}} utworzona:",
"versionID": "ID wersji",
"versions": "Wersje",

View File

@@ -60,6 +60,7 @@
"accountAlreadyActivated": "Essa conta já foi ativada.",
"autosaving": "Ocorreu um problema ao salvar automaticamente esse documento.",
"correctInvalidFields": "Por favor, corrija os campos inválidos.",
"deletingFile": "Ocorreu um erro ao excluir o arquivo.",
"deletingTitle": "Ocorreu um erro ao excluir {{title}}. Por favor, verifique sua conexão e tente novamente.",
"emailOrPasswordIncorrect": "O email ou senha fornecido está incorreto.",
"followingFieldsInvalid_many": "Os campos a seguir estão inválidos:",
@@ -81,6 +82,8 @@
"problemUploadingFile": "Ocorreu um problema ao carregar o arquivo.",
"tokenInvalidOrExpired": "Token expirado ou inválido.",
"unPublishingDocument": "Ocorreu um problema ao despublicar esse documento",
"unableToDeleteCount": "Não é possível excluir {{count}} de {{total}} {{label}}.",
"unableToUpdateCount": "Não foi possível atualizar {{count}} de {{total}} {{label}}.",
"unauthorized": "Não autorizado. Você deve estar logado para fazer essa requisição",
"unknown": "Ocorreu um erro desconhecido.",
"unspecific": "Ocorreu um erro.",
@@ -89,27 +92,34 @@
"verificationTokenInvalid": "Token de verificação inválido."
},
"fields": {
"block": "bloco",
"blocks": "blocos",
"addLabel": "Adicionar {{label}}",
"addLink": "Adicionar Link",
"addNew": "Adicionar novo",
"addNewLabel": "Adicionar novo {{label}}",
"addRelationship": "Adicionar Relação",
"addUpload": "Adicionar Upload",
"block": "bloco",
"blockType": "Tipo de bloco",
"blocks": "blocos",
"chooseBetweenCustomTextOrDocument": "Escolha entre inserir um URL de texto personalizado ou vincular a outro documento.",
"chooseDocumentToLink": "Escolha um documento para vincular",
"chooseFromExisting": "Escolher entre os existentes",
"chooseLabel": "Escolher {{label}}",
"collapseAll": "Recolher todos",
"customURL": "URL personalizado",
"editLabelData": "Editar dados de {{label}}",
"editLink": "Editar Link",
"editRelationship": "Editar Relacionamento",
"enterURL": "Insira um URL",
"internalLink": "Link Interno",
"itemsAndMore": "{{items}} e mais {{count}}",
"labelRelationship": "Relacionado a {{label}}",
"latitude": "Latitude",
"linkType": "Tipo de link",
"linkedTo": "Ligado a <0>{{label}}</0>",
"longitude": "Longitude",
"newLabel": "Novo(a) {{label}}",
"openInNewTab": "Abrir em nova aba",
"passwordsDoNotMatch": "Senhas não coincidem.",
"relatedDocument": "Documento Relacionado",
"relationTo": "Relacionado a",
@@ -118,18 +128,24 @@
"saveChanges": "Salvar alterações",
"searchForBlock": "Procurar bloco",
"selectExistingLabel": "Selecionar {{label}} existente",
"selectFieldsToEdit": "Selecione os campos para editar",
"showAll": "Mostrar Tudo",
"swapRelationship": "Relação de Troca",
"swapUpload": "Substituir Upload",
"textToDisplay": "Texto a ser exibido",
"toggleBlock": "Alternar bloco",
"uploadNewLabel": "Carregar novo(a) {{label}}"
},
"general": {
"aboutToDelete": "Você está prestes a excluir o/a {{label}} <1>{{title}}</1>. Tem certeza?",
"aboutToDeleteCount_many": "Você está prestes a deletar {{count}} {{label}}",
"aboutToDeleteCount_one": "Você está prestes a deletar {{count}} {{label}}",
"aboutToDeleteCount_other": "Você está prestes a deletar {{count}} {{label}}",
"addBelow": "Adicionar abaixo",
"addFilter": "Adicionar Filtro",
"adminTheme": "Tema do Admin",
"and": "E",
"ascending": "Ascendente",
"automatic": "Automático",
"backToDashboard": "Voltar para Painel de Controle",
"cancel": "Cancelar",
@@ -152,6 +168,7 @@
"dark": "Escuro",
"dashboard": "Painel de Controle",
"delete": "Excluir",
"deletedCountSuccessfully": "Excluído {{count}} {{label}} com sucesso.",
"deletedSuccessfully": "Apagado com sucesso.",
"deleting": "Excluindo...",
"descending": "Decrescente",
@@ -160,6 +177,9 @@
"edit": "Editar",
"editLabel": "Editar {{label}}",
"editing": "Editando",
"editingLabel_many": "Editando {{count}} {{label}}",
"editingLabel_one": "Editando {{count}} {{label}}",
"editingLabel_other": "Editando {{count}} {{label}}",
"email": "Email",
"emailAddress": "Endereço de Email",
"enterAValue": "Insira um valor",
@@ -198,7 +218,9 @@
"save": "Salvar",
"saving": "Salvando...",
"searchBy": "Buscar por {{label}}",
"selectAll": "Selecione tudo {{count}} {{label}}",
"selectValue": "Selecione um valor",
"selectedCount": "{{count}} {{label}} selecionado",
"sorryNotFound": "Desculpe—não há nada que corresponda à sua requisição.",
"sort": "Ordenar",
"stayOnThisPage": "Permanecer nessa página",
@@ -212,6 +234,7 @@
"unsavedChangesDuplicate": "Você tem mudanças não salvas. Você gostaria de continuar a duplicar?",
"untitled": "Sem título",
"updatedAt": "Atualizado Em",
"updatedCountSuccessfully": "Atualizado {{count}} {{label}} com sucesso.",
"updatedSuccessfully": "Atualizado com sucesso.",
"updating": "Atualizando",
"uploading": "Fazendo upload",
@@ -220,20 +243,21 @@
"welcome": "Boas vindas"
},
"operators": {
"contains": "contém",
"equals": "igual",
"isNotEqualTo": "não é igual a",
"isIn": "está em",
"isNotIn": "não está em",
"exists": "existe",
"isGreaterThan": "é maior que",
"isGreaterThanOrEqualTo": "é maior ou igual a",
"isIn": "está em",
"isLessThan": "é menor que",
"isLessThanOrEqualTo": "é menor ou igual a",
"isGreaterThanOrEqualTo": "é maior ou igual a",
"near": "perto",
"isLike": "é como",
"contains": "contém"
"isNotEqualTo": "não é igual a",
"isNotIn": "não está em",
"near": "perto"
},
"upload": {
"dragAndDrop": "Arraste e solte um arquivo",
"dragAndDropHere": "ou arraste um arquivo aqui",
"fileName": "Nome do Arquivo",
"fileSize": "Tamanho do Arquivo",
@@ -242,7 +266,6 @@
"moreInfo": "Ver mais",
"selectCollectionToBrowse": "Selecione uma Coleção para Navegar",
"selectFile": "Selecione um arquivo",
"dragAndDrop": "Arraste e solte um arquivo",
"sizes": "Tamanhos",
"width": "Largura"
},
@@ -266,15 +289,18 @@
"validUploadID": "'Esse campo não é um ID de upload válido.'"
},
"version": {
"aboutToPublishSelection": "Você está prestes a publicar todos os {{label}} da seleção. Tem certeza?",
"aboutToRestore": "Você está prestes a restaurar o documento {{label}} para o estado em que ele se encontrava em {{versionDate}}.",
"aboutToRestoreGlobal": "Você está prestes a restaurar o Global {{label}} para o estado em que ele se encontrava em {{versionDate}}.",
"aboutToRevertToPublished": "Você está prestes a reverter as alterações desse documento para seu estado de publicação. Tem certeza?",
"aboutToUnpublish": "Você está prestes a despublicar esse documento. Tem certeza?",
"aboutToUnpublishSelection": "Você está prestes a cancelar a publicação de todos os {{label}} na seleção. Tem certeza?",
"autosave": "Salvamento automático",
"autosavedSuccessfully": "Salvamento automático com sucesso.",
"autosavedVersion": "Versão de salvamento automático",
"changed": "Alterado",
"compareVersion": "Comparar versão com:",
"confirmPublish": "Confirmar publicação",
"confirmRevertToSaved": "Confirmar a reversão para o salvo",
"confirmUnpublish": "Confirmar despublicação",
"confirmVersionRestoration": "Confirmar Restauração de versão",
@@ -286,6 +312,7 @@
"noRowsFound": "Nenhum(a) {{label}} encontrado(a)",
"preview": "Pré-visualização",
"problemRestoringVersion": "Ocorreu um problema ao restaurar essa versão",
"publish": "Publicar",
"publishChanges": "Publicar alterações",
"published": "Publicado",
"restoreThisVersion": "Restaurar essa versão",
@@ -297,6 +324,7 @@
"selectLocales": "Selecione as localizações para exibir",
"selectVersionToCompare": "Selecione uma versão para comparar",
"showLocales": "Exibir localizações:",
"showingVersionsFor": "Mostrando versões para:",
"status": "Status",
"type": "Tipo",
"unpublish": "Despublicar",
@@ -305,6 +333,7 @@
"versionCount_many": "{{count}} versões encontradas",
"versionCount_none": "Nenhuma versão encontrada",
"versionCount_one": "{{count}} versão encontrada",
"versionCount_other": "{{count}} versões encontradas",
"versionCreatedOn": "{{version}} criada em:",
"versionID": "ID da versão",
"versions": "Versões",

View File

@@ -82,6 +82,8 @@
"problemUploadingFile": "Возникла проблема при загрузке файла.",
"tokenInvalidOrExpired": "Токен либо недействителен, либо срок его действия истек.",
"unPublishingDocument": "При отмене публикации этого документа возникла проблема.",
"unableToDeleteCount": "Не удалось удалить {{count}} из {{total}} {{label}}.",
"unableToUpdateCount": "Не удалось обновить {{count}} из {{total}} {{label}}.",
"unauthorized": "Нет доступа, вы должны войти, чтобы сделать этот запрос.",
"unknown": "Произошла неизвестная ошибка.",
"unspecific": "Произошла ошибка.",
@@ -126,6 +128,7 @@
"saveChanges": "Сохранить изменения",
"searchForBlock": "Найти Блок",
"selectExistingLabel": "Выберите существующий {{label}}",
"selectFieldsToEdit": "Выберите поля для редактирования",
"showAll": "Показать все",
"swapRelationship": "Поменять отношения",
"swapUpload": "Заменить загруженное",
@@ -135,10 +138,14 @@
},
"general": {
"aboutToDelete": "Вы собираетесь удалить {{label}} <1>{{title}}</1>. Вы уверены?",
"aboutToDeleteCount_many": "Вы собираетесь удалить {{count}} {{label}}",
"aboutToDeleteCount_one": "Вы собираетесь удалить {{count}} {{label}}",
"aboutToDeleteCount_other": "Вы собираетесь удалить {{count}} {{label}}",
"addBelow": "Добавить ниже",
"addFilter": "Добавить фильтр",
"adminTheme": "Тема Панели",
"and": "А также",
"ascending": "Восходящий",
"automatic": "Автоматически",
"backToDashboard": "Назад к Панели",
"cancel": "Отмена",
@@ -161,6 +168,7 @@
"dark": "Тёмная",
"dashboard": "Панель",
"delete": "Удалить",
"deletedCountSuccessfully": "Удалено {{count}} {{label}} успешно.",
"deletedSuccessfully": "Удален успешно.",
"deleting": "Удаление...",
"descending": "Уменьшение",
@@ -169,6 +177,9 @@
"edit": "Редактировать",
"editLabel": "Редактировать {{label}}",
"editing": "Редактирование",
"editingLabel_many": "Редактирование {{count}} {{label}}",
"editingLabel_one": "Редактирование {{count}} {{label}}",
"editingLabel_other": "Редактирование {{count}} {{label}}",
"email": "Email",
"emailAddress": "Email",
"enterAValue": "Введите значение",
@@ -207,7 +218,9 @@
"save": "Сохранить",
"saving": "Сохранение...",
"searchBy": "Искать по",
"selectAll": "Выбрать все {{count}} {{label}}",
"selectValue": "Выбрать значение",
"selectedCount": "{{count}} {{label}} выбрано",
"sorryNotFound": "К сожалению, ничего подходящего под ваш запрос нет.",
"sort": "Сортировать",
"stayOnThisPage": "Остаться на этой странице",
@@ -221,6 +234,7 @@
"unsavedChangesDuplicate": "У вас есть несохраненные изменения. Вы хотите продолжить дублирование?",
"untitled": "Без названия",
"updatedAt": "Дата правки",
"updatedCountSuccessfully": "Обновлено {{count}} {{label}} успешно.",
"updatedSuccessfully": "Успешно Обновлено.",
"updating": "Обновление",
"uploading": "Загрузка",
@@ -229,20 +243,21 @@
"welcome": "Добро пожаловать"
},
"operators": {
"contains": "содержит",
"equals": "равно",
"isNotEqualTo": "не равно",
"isIn": "находится",
"isNotIn": "нет в",
"exists": "существует",
"isGreaterThan": "больше чем",
"isGreaterThanOrEqualTo": "больше или равно",
"isIn": "находится",
"isLessThan": "меньше чем",
"isLessThanOrEqualTo": "меньше или равно",
"isGreaterThanOrEqualTo": "больше или равно",
"near": "рядом",
"isLike": "похоже",
"contains": "содержит"
"isNotEqualTo": "не равно",
"isNotIn": "нет в",
"near": "рядом"
},
"upload": {
"dragAndDrop": "Перетащите файл",
"dragAndDropHere": "или перетащите файл сюда",
"fileName": "Имя файла",
"fileSize": "Размер файла",
@@ -251,7 +266,6 @@
"moreInfo": "Больше информации",
"selectCollectionToBrowse": "Выберите Коллекцию для просмотра",
"selectFile": "Выберите файл",
"dragAndDrop": "Перетащите файл",
"sizes": "Размеры",
"width": "Ширина"
},
@@ -265,25 +279,28 @@
"invalidSelections": "'Это поле содержит следующие неправильные варианты:'",
"lessThanMin": "\"{{value}}\" меньше минимально допустимого значения {{min}}.",
"longerThanMin": "Это значение должно быть больше минимальной длины символов: {{minLength}}.",
"requiresAtLeast": "Это поле требует не менее {{count}} {{label}}",
"requiresNoMoreThan": "Это поле требует не более {{count}} {{label}}",
"notValidDate": "\"{{value}}\" это не действительная дата.",
"required": "Это обязательное поле.",
"requiresAtLeast": "Это поле требует не менее {{count}} {{label}}",
"requiresNoMoreThan": "Это поле требует не более {{count}} {{label}}",
"requiresTwoNumbers": "В этом поле требуется два числа.",
"shorterThanMax": "Это значение должно быть короче максимальной длины символов {{maxLength}}.",
"trueOrFalse": "Это поле может быть равно только true или false.",
"validUploadID": "'Это поле не является действительным ID загрузки.'"
},
"version": {
"aboutToPublishSelection": "Вы собираетесь опубликовать все {{label}} в выборе. Вы уверены?",
"aboutToRestore": "Вы собираетесь восстановить этот документ {{label}} в состояние, в котором он находился {{versionDate}}.",
"aboutToRestoreGlobal": "Вы собираетесь восстановить глобальную запись {{label}} в состояние, в котором она находилась {{versionDate}}.",
"aboutToRevertToPublished": "Вы собираетесь вернуть изменения этого документа к его опубликованному состоянию. Вы уверены?",
"aboutToUnpublish": "Вы собираетесь отменить публикацию этого документа. Вы уверены?",
"aboutToUnpublishSelection": "Вы собираетесь отменить публикацию всех выбранных {{label}}. Вы уверены?",
"autosave": "Автосохранение",
"autosavedSuccessfully": "Автосохранение успешно.",
"autosavedVersion": "Автоматически сохраненная версия",
"changed": "Изменено",
"compareVersion": "Сравнить версию с:",
"confirmPublish": "Подтвердить публикацию",
"confirmRevertToSaved": "Подтвердить возврат к сохраненному",
"confirmUnpublish": "Подтвердить отмену публикации",
"confirmVersionRestoration": "Подтвердить восстановление версии",
@@ -295,6 +312,7 @@
"noRowsFound": "Не найдено {{label}}",
"preview": "Предпросмотр",
"problemRestoringVersion": "Возникла проблема с восстановлением этой версии",
"publish": "Публиковать",
"publishChanges": "Опубликовать изменения",
"published": "Опубликовано",
"restoreThisVersion": "Восстановить эту версию",
@@ -305,8 +323,8 @@
"saveDraft": "Сохранить черновик",
"selectLocales": "Выберите локали для отображения",
"selectVersionToCompare": "Выбрать версию для сравнения",
"showingVersionsFor": "Показаны версии для:",
"showLocales": "Показать локали:",
"showingVersionsFor": "Показаны версии для:",
"status": "Статус",
"type": "Тип",
"unpublish": "Отменить публикацию",

View File

@@ -82,6 +82,8 @@
"problemUploadingFile": "Det uppstod ett problem när filen laddades upp.",
"tokenInvalidOrExpired": "Token är antingen ogiltig eller har löpt ut.",
"unPublishingDocument": "Det uppstod ett problem när det här dokumentet skulle avpubliceras.",
"unableToDeleteCount": "Det gick inte att ta bort {{count}} av {{total}} {{label}}.",
"unableToUpdateCount": "Det gick inte att uppdatera {{count}} av {{total}} {{label}}.",
"unauthorized": "Obehörig, du måste vara inloggad för att göra denna begäran.",
"unknown": "Ett okänt fel har uppstått.",
"unspecific": "Ett fel har uppstått.",
@@ -90,27 +92,34 @@
"verificationTokenInvalid": "Verifieringstoken är ogiltig."
},
"fields": {
"block": "block",
"blocks": "block",
"addLabel": "Lägg till {{label}}",
"addLink": "Lägg till Länk",
"addNew": "Lägg till ny",
"addNewLabel": "Lägg till ny {{label}}",
"addRelationship": "Lägg till Relation",
"addUpload": "Lägg till Uppladdning",
"block": "block",
"blockType": "Block Typ",
"blocks": "block",
"chooseBetweenCustomTextOrDocument": "Välj mellan att ange en anpassad text-URL eller länka till ett annat dokument.",
"chooseDocumentToLink": "Välj ett dokument att länka till",
"chooseFromExisting": "Välj bland befintliga",
"chooseLabel": "Välj {{label}}",
"collapseAll": "kollapsa Alla",
"customURL": "Anpassad URL",
"editLabelData": "Redigera {{label}} data",
"editLink": "Redigera Länk",
"editRelationship": "Redigera Relation",
"enterURL": "Ange en URL",
"internalLink": "Intern länk",
"itemsAndMore": "{{items}} och {{count}} mer",
"labelRelationship": "{{label}} Relation",
"latitude": "Latitud",
"linkType": "Länktyp",
"linkedTo": "Länkad till <0>{{label}}</0>",
"longitude": "Longitud",
"newLabel": "Ny {{label}}",
"openInNewTab": "Öppna i ny flik",
"passwordsDoNotMatch": "Lösenorden matchar inte.",
"relatedDocument": "Relaterat Dokument",
"relationTo": "Relation till",
@@ -119,18 +128,24 @@
"saveChanges": "Spara ändringar",
"searchForBlock": "Sök efter ett block",
"selectExistingLabel": "Välj befintlig {{label}}",
"selectFieldsToEdit": "Välj fält att redigera",
"showAll": "Visa Alla",
"swapRelationship": "Byt Förhållande",
"swapUpload": "Byt Uppladdning",
"textToDisplay": "Text att visa",
"toggleBlock": "Växla block",
"uploadNewLabel": "Ladda upp ny {{label}}"
},
"general": {
"aboutToDelete": "Du är på väg att ta bort {{label}} <1>{{title}}</1>. Är du säker?",
"aboutToDeleteCount_many": "Du är på väg att ta bort {{count}} {{label}}",
"aboutToDeleteCount_one": "Du är på väg att ta bort {{count}} {{label}}",
"aboutToDeleteCount_other": "Du är på väg att ta bort {{count}} {{label}}",
"addBelow": "Lägg Till Nedanför",
"addFilter": "Lägg Till Filter",
"adminTheme": "Admin Tema",
"and": "Och",
"ascending": "Stigande",
"automatic": "Automatisk",
"backToDashboard": "Tillbaka till Manöverpanelen",
"cancel": "Avbryt",
@@ -153,6 +168,7 @@
"dark": "Mörk",
"dashboard": "Manöverpanel",
"delete": "Ta bort",
"deletedCountSuccessfully": "Raderade {{count}} {{label}} framgångsrikt.",
"deletedSuccessfully": "Togs bort framgångsrikt.",
"deleting": "Tar bort...",
"descending": "Fallande",
@@ -161,6 +177,9 @@
"edit": "Redigera",
"editLabel": "Redigera {{label}}",
"editing": "Redigerar",
"editingLabel_many": "Redigerar {{count}} {{label}}",
"editingLabel_one": "Redigerar {{count}} {{label}}",
"editingLabel_other": "Redigerar {{count}} {{label}}",
"email": "E-post",
"emailAddress": "E-postadress",
"enterAValue": "Ange ett värde",
@@ -199,7 +218,9 @@
"save": "Spara",
"saving": "Sparar...",
"searchBy": "Sök efter {{label}}",
"selectAll": "Välj alla {{count}} {{label}}",
"selectValue": "Välj ett värde",
"selectedCount": "{{count}} {{label}} har valts",
"sorryNotFound": "Tyvärrdet finns inget som motsvarar din begäran.",
"sort": "Sortera",
"stayOnThisPage": "Stanna på denna sida",
@@ -213,6 +234,7 @@
"unsavedChangesDuplicate": "Du har osparade ändringar. Vill du fortsätta att duplicera?",
"untitled": "Namnlös",
"updatedAt": "Uppdaterades Vid",
"updatedCountSuccessfully": "Uppdaterade {{count}} {{label}} framgångsrikt.",
"updatedSuccessfully": "Uppdaterades framgångsrikt.",
"updating": "Uppdatering",
"uploading": "Uppladdning",
@@ -221,20 +243,21 @@
"welcome": "Välkommen"
},
"operators": {
"contains": "innehåller",
"equals": "likar med",
"isNotEqualTo": "är inte lika med",
"isIn": "är med",
"isNotIn": "är inte med",
"exists": "finns",
"isGreaterThan": "är större än",
"isGreaterThanOrEqualTo": "är större än eller lika med",
"isIn": "är med",
"isLessThan": "är mindre än",
"isLessThanOrEqualTo": "är mindre än eller lika med",
"isGreaterThanOrEqualTo": "är större än eller lika med",
"near": "nära",
"isLike": "är som",
"contains": "innehåller"
"isNotEqualTo": "är inte lika med",
"isNotIn": "är inte med",
"near": "nära"
},
"upload": {
"dragAndDrop": "Dra och släpp en fil",
"dragAndDropHere": "eller dra och släpp en fil här",
"fileName": "Filnamn",
"fileSize": "Filstorlek",
@@ -243,7 +266,6 @@
"moreInfo": "Mer info",
"selectCollectionToBrowse": "Välj en Samling att Bläddra i",
"selectFile": "Välj en fil",
"dragAndDrop": "Dra och släpp en fil",
"sizes": "Storlekar",
"width": "Bredd"
},
@@ -267,15 +289,18 @@
"validUploadID": "Det här fältet är inte ett giltigt uppladdnings-ID"
},
"version": {
"aboutToPublishSelection": "Du är på väg att publicera alla {{label}} i urvalet. Är du säker?",
"aboutToRestore": "Du är på väg att återställa detta {{label}} dokumentet till det tillståndet som det var den {{versionDate}}.",
"aboutToRestoreGlobal": "Du är på väg att återställa det globala {{label}} till det tillståndet som det var den {{versionDate}}.",
"aboutToRevertToPublished": "Du är på väg att återställa det här dokumentets ändringar till dess publicerade tillstånd. Är du säker?",
"aboutToUnpublish": "Du håller på att avpublicera detta dokumentet. Är du säker?",
"aboutToUnpublishSelection": "Du är på väg att avpublicera alla {{label}} i urvalet. Är du säker?",
"autosave": "Automatisk sparning",
"autosavedSuccessfully": "Autosparades framgångsrikt.",
"autosavedVersion": "Autosparad version",
"changed": "Ändrad",
"compareVersion": "Jämför version med:",
"confirmPublish": "Bekräfta publicering",
"confirmRevertToSaved": "Bekräfta återgång till sparad",
"confirmUnpublish": "Bekräfta avpublicering",
"confirmVersionRestoration": "Bekräfta Versionsåterställning",
@@ -287,6 +312,7 @@
"noRowsFound": "Inga {{label}} hittades",
"preview": "Förhandsvisa",
"problemRestoringVersion": "Det uppstod ett problem när den här versionen skulle återställas",
"publish": "Publicera",
"publishChanges": "Publicera ändringar",
"published": "Publicerad",
"restoreThisVersion": "Återställ den här versionen",
@@ -298,6 +324,7 @@
"selectLocales": "Välj språk att visa",
"selectVersionToCompare": "Välj en version att jämföra",
"showLocales": "Visa språk:",
"showingVersionsFor": "Visar versioner för:",
"status": "Status",
"type": "Typ",
"unpublish": "Avpublicera",
@@ -306,6 +333,7 @@
"versionCount_many": "{{count}} versioner hittades",
"versionCount_none": "Inga versioner hittades",
"versionCount_one": "{{count}} version hittades",
"versionCount_other": "{{count}} versioner hittades",
"versionCreatedOn": "{{version}} skapad den:",
"versionID": "Versions-ID",
"versions": "Versioner",

View File

@@ -82,6 +82,8 @@
"problemUploadingFile": "เกิดปัญหาระหว่างการอัปโหลดไฟล์",
"tokenInvalidOrExpired": "Token ไม่ถูกต้องหรือหมดอายุ",
"unPublishingDocument": "เกิดปัญหาระหว่างการยกเลิกการเผยแพร่เอกสารนี้",
"unableToDeleteCount": "ไม่สามารถลบ {{count}} จาก {{total}} {{label}}",
"unableToUpdateCount": "ไม่สามารถอัปเดต {{count}} จาก {{total}} {{label}}",
"unauthorized": "คุณไม่ได้รับอนุญาต กรุณาเข้าสู่ระบบเพื่อทำคำขอนี้",
"unknown": "เกิดปัญหาบางอย่างที่ไม่ทราบสาเหตุ",
"unspecific": "เกิดปัญหาบางอย่าง",
@@ -91,8 +93,8 @@
},
"fields": {
"addLabel": "เพิ่ม {{label}}",
"addNew": "เพิ่ม",
"addLink": "เพิ่มลิงค์",
"addNew": "เพิ่ม",
"addNewLabel": "เพิ่ม {{label}} ใหม่",
"addRelationship": "เพิ่มความสัมพันธ์",
"addUpload": "เพิ่มการอัปโหลด",
@@ -126,6 +128,7 @@
"saveChanges": "บันทึก",
"searchForBlock": "ค้นหา Block",
"selectExistingLabel": "เลือก {{label}} ที่มีอยู่",
"selectFieldsToEdit": "เลือกช่องที่จะแก้ไข",
"showAll": "แสดงทั้งหมด",
"swapRelationship": "สลับความสัมพันธ์",
"swapUpload": "สลับอัปโหลด",
@@ -135,6 +138,9 @@
},
"general": {
"aboutToDelete": "คุณกำลังจะลบ {{label}} <1>{{title}}</1> ต้องการดำเนินการต่อหรือไม่?",
"aboutToDeleteCount_many": "คุณกำลังจะลบ {{count}} {{label}}",
"aboutToDeleteCount_one": "คุณกำลังจะลบ {{count}} {{label}}",
"aboutToDeleteCount_other": "คุณกำลังจะลบ {{count}} {{label}}",
"addBelow": "เพิ่มด้านล่าง",
"addFilter": "เพิ่มการกรอง",
"adminTheme": "ธีมผู้ดูแลระบบ",
@@ -162,6 +168,7 @@
"dark": "มืด",
"dashboard": "แดชบอร์ด",
"delete": "ลบ",
"deletedCountSuccessfully": "Deleted {{count}} {{label}} successfully.",
"deletedSuccessfully": "ลบสำเร็จ",
"deleting": "กำลังลบ...",
"descending": "มากไปน้อย",
@@ -170,6 +177,9 @@
"edit": "แก้ไข",
"editLabel": "แก้ไข {{label}}",
"editing": "แก้ไข",
"editingLabel_many": "กำลังแก้ไข {{count}} {{label}}",
"editingLabel_one": "กำลังแก้ไข {{count}} {{label}}",
"editingLabel_other": "กำลังแก้ไข {{count}} {{label}}",
"email": "อีเมล",
"emailAddress": "อีเมล",
"enterAValue": "ระบุค่า",
@@ -208,7 +218,9 @@
"save": "บันทึก",
"saving": "กำลังบันทึก...",
"searchBy": "ค้นหาด้วย {{label}}",
"selectAll": "เลือกทั้งหมด {{count}} {{label}}",
"selectValue": "เลือกค่า",
"selectedCount": "เลือก {{count}} {{label}} แล้ว",
"sorryNotFound": "ขออภัย ไม่สามารถทำตามคำขอของคุณได้",
"sort": "เรียง",
"stayOnThisPage": "อยู่หน้านี้ต่อ",
@@ -222,6 +234,7 @@
"unsavedChangesDuplicate": "คุณมีการแก้ไขที่ยังไม่ถูกบันทึก คุณต้องการทำสำเนาต่อหรือไม่?",
"untitled": "ไม่มีชื่อ",
"updatedAt": "แก้ไขเมื่อ",
"updatedCountSuccessfully": "อัปเดต {{count}} {{label}} เรียบร้อยแล้ว",
"updatedSuccessfully": "แก้ไขสำเร็จ",
"updating": "กำลังอัปเดต",
"uploading": "กำลังอัปโหลด",
@@ -230,20 +243,21 @@
"welcome": "ยินดีต้อนรับ"
},
"operators": {
"contains": "มี",
"equals": "เท่ากับ",
"isNotEqualTo": "ไม่เท่ากับ",
"isIn": "อยู่ใน",
"isNotIn": "ไม่ได้อยู่ใน",
"exists": "มีอยู่",
"isGreaterThan": "มากกว่า",
"isGreaterThanOrEqualTo": "มากกว่าหรือเท่ากับ",
"isIn": "อยู่ใน",
"isLessThan": "น้อยกว่า",
"isLessThanOrEqualTo": "น้อยกว่าหรือเท่ากับ",
"isGreaterThanOrEqualTo": "มากกว่าหรือเท่ากับ",
"near": "ใกล้",
"isLike": "เหมือน",
"contains": "มี"
"isNotEqualTo": "ไม่เท่ากับ",
"isNotIn": "ไม่ได้อยู่ใน",
"near": "ใกล้"
},
"upload": {
"dragAndDrop": "ลากและวางไฟล์",
"dragAndDropHere": "หรือลากและวางไฟล์ที่นี่",
"fileName": "ชื่อไฟล์",
"fileSize": "ขนาดไฟล์",
@@ -252,7 +266,6 @@
"moreInfo": "แสดงข้อมูล",
"selectCollectionToBrowse": "เลือก Collection ที่ต้องการค้นหา",
"selectFile": "เลือกไฟล์",
"dragAndDrop": "ลากและวางไฟล์",
"sizes": "ขนาด",
"width": "ความกว้าง"
},
@@ -276,15 +289,18 @@
"validUploadID": "ไม่ใช่ ID ของการอัปโหลดที่ถูกต้อง"
},
"version": {
"aboutToPublishSelection": "คุณกำลังจะเผยแพร่ {{label}} ทั้งหมดในส่วนที่เลือก คุณแน่ใจไหม?",
"aboutToRestore": "คุณกำลังจะคืนค่าเอกสาร {{label}} นี้กลับไปอยู่ในเวอร์ชันเมื่อวันที่ {{versionDate}}",
"aboutToRestoreGlobal": "คุณกำลังจะคืนค่า global {{label}} กลับไปอยู่ในเวอร์ชันเมื่อวันที่ {{versionDate}}.",
"aboutToRevertToPublished": "คุณกำลังจะย้อนการเปลี่ยนแปลงของเอกสารนี้ไปยังเวอร์ชันที่เผยแพร่อยู่ คุณต้องการดำเนินการต่อหรือไม่?",
"aboutToUnpublish": "คุณกำลังจะยกเลิกเผยแพร่เอกสารนี้ คุณต้องการดำเนินการต่อหรือไม่?",
"aboutToUnpublishSelection": "คุณกำลังจะเลิกเผยแพร่ {{label}} ทั้งหมดในส่วนที่เลือก คุณแน่ใจไหม?",
"autosave": "บันทึกอัตโนมัติ",
"autosavedSuccessfully": "บันทึกอัตโนมัติสำเร็จ",
"autosavedVersion": "เวอร์ชันบันทึกอัตโนมัติ",
"changed": "มีการแก้ไข",
"compareVersion": "เปรียบเทียบเวอร์ชันกับ:",
"confirmPublish": "ยืนยันการเผยแพร่",
"confirmRevertToSaved": "ยืนยันย้อนการแก้ไข",
"confirmUnpublish": "ยืนยันการยกเลิกการเผยแพร่",
"confirmVersionRestoration": "ยืนยันการกู้คืนเวอร์ชัน",
@@ -296,6 +312,7 @@
"noRowsFound": "ไม่พบ {{label}}",
"preview": "ตัวอย่าง",
"problemRestoringVersion": "เกิดปัญหาระหว่างการกู้คืนเวอร์ชันนี้",
"publish": "เผยแพร่",
"publishChanges": "เผยแพร่การแก้ไข",
"published": "เผยแพร่แล้ว",
"restoreThisVersion": "กู้คืนเวอร์ชันนี้",
@@ -306,8 +323,8 @@
"saveDraft": "บันทึกร่าง",
"selectLocales": "เลือกภาษาที่ต้องการแสดง",
"selectVersionToCompare": "เลือกเวอร์ชันที่ต้องการเปรียบเทียบ",
"showingVersionsFor": "กำลังแสดงเวอร์ชันของ:",
"showLocales": "แสดงภาษา:",
"showingVersionsFor": "กำลังแสดงเวอร์ชันของ:",
"status": "สถานะ",
"type": "ประเภท",
"unpublish": "หยุดเผยแพร่",

View File

@@ -60,6 +60,7 @@
"accountAlreadyActivated": "Hesap zaten etkinleştirildi.",
"autosaving": "Otomatik kaydetme başarısız oldu",
"correctInvalidFields": "Lütfen geçersiz alanları düzeltin.",
"deletingFile": "Dosya silinirken bir hatayla karşılaşıldı.",
"deletingTitle": "{{title}} silinirken bir sorun yaşandı. Lütfen internet bağlantınızı kontrol edip tekrar deneyin.",
"emailOrPasswordIncorrect": "Girilen e-posta veya parola hatalı",
"followingFieldsInvalid_many": "Lütfen geçersiz alanları düzeltin:",
@@ -81,44 +82,44 @@
"problemUploadingFile": "Dosya yüklenirken bir sorun oluştu.",
"tokenInvalidOrExpired": "Geçersiz veya süresi dolmuş token.",
"unPublishingDocument": "Geçerli döküman yayından kaldırılırken bir sorun oluştu.",
"unableToDeleteCount": "{{total}} {{label}} içinden {{count}} silinemiyor.",
"unableToUpdateCount": "{{total}} {{label}} içinden {{count}} güncellenemiyor.",
"unauthorized": "Bu işlemi gerçekleştirmek için lütfen giriş yapın.",
"unknown": "Bilinmeyen bir hata oluştu.",
"unspecific": "Bir hata oluştu.",
"userLocked": "Hesabınız hatalı giriş denemeleri yüzünden geçici olarak kilitlendi. Lütfen daha sonra tekrar deneyin.",
"valueMustBeUnique": "Değer benzersiz olmalıdır",
"verificationTokenInvalid": "Doğrulama tokeni geçersiz.",
"deletingFile": "Dosya silinirken bir hatayla karşılaşıldı."
"verificationTokenInvalid": "Doğrulama tokeni geçersiz."
},
"fields": {
"chooseBetweenCustomTextOrDocument": "Choose between entering a custom text URL or linking to another document.",
"chooseDocumentToLink": "Bağlantı verilecek bir döküman seçin.",
"customURL": "Özel URL",
"editLink": "Bağlantıyı Düzenle",
"editRelationship": "İlişkiyi Ekle",
"enterURL": "Bir URL girin",
"internalLink": "İç bağlantı",
"linkType": "Bağlantı türü",
"openInNewTab": "Yeni sekmede aç",
"textToDisplay": "Görüntülenecek metin",
"block": "blok",
"blocks": "blok",
"addLabel": "{{label}} ekle",
"addLink": "Link Ekle",
"addNew": "Yeni",
"addNewLabel": "Yeni {{label}}",
"addRelationship": "İlişki Ekle",
"addUpload": "Yükleme Ekle",
"block": "blok",
"blockType": "Blok tipi",
"blocks": "blok",
"chooseBetweenCustomTextOrDocument": "Choose between entering a custom text URL or linking to another document.",
"chooseDocumentToLink": "Bağlantı verilecek bir döküman seçin.",
"chooseFromExisting": "Varolanlardan seç",
"chooseLabel": "{{label}} seç",
"collapseAll": "Tümünü daralt",
"customURL": "Özel URL",
"editLabelData": "{{label}} düzenle",
"editLink": "Bağlantıyı Düzenle",
"editRelationship": "İlişkiyi Ekle",
"enterURL": "Bir URL girin",
"internalLink": "İç bağlantı",
"itemsAndMore": "{{items}} and {{count}} more",
"labelRelationship": "{{label}} Relationship",
"latitude": "Enlem",
"linkType": "Bağlantı türü",
"linkedTo": "<0>label</0> için bağlantı verildi",
"longitude": "Boylam",
"newLabel": "Yeni {{label}}",
"openInNewTab": "Yeni sekmede aç",
"passwordsDoNotMatch": "Parolalar eşleşmiyor.",
"relatedDocument": "İlişkili döküman",
"relationTo": "Relation To",
@@ -127,22 +128,24 @@
"saveChanges": "Değişiklikleri kaydet",
"searchForBlock": "Blok ara",
"selectExistingLabel": "Varolan {{label}} seç",
"selectFieldsToEdit": "Düzenlenecek alanları seçin",
"showAll": "Tümünü göster",
"swapRelationship": "Takas Ilişkisi",
"swapUpload": "Karşıya Yüklemeyi Değiştir",
"textToDisplay": "Görüntülenecek metin",
"toggleBlock": "Bloğu aç/kapat",
"uploadNewLabel": "Karşıya {{label}} yükle"
},
"general": {
"addBelow": "Altına ekle",
"filter": "Filtrele",
"none": "Hiç",
"enterAValue": "Değer girin",
"deletedSuccessfully": "Başarıyla silindi.",
"aboutToDelete": "<1>{{title}}</1> {{label}} silinmek üzere. Silme işlemine devam etmek istiyor musunuz?",
"aboutToDeleteCount_many": "{{count}} {{label}} silmek üzeresiniz",
"aboutToDeleteCount_one": "{{count}} {{label}} silmek üzeresiniz",
"aboutToDeleteCount_other": "{{count}} {{label}} silmek üzeresiniz",
"addBelow": "Altına ekle",
"addFilter": "Filtre ekle",
"adminTheme": "Admin arayüzü",
"and": "ve",
"ascending": "artan",
"automatic": "Otomatik",
"backToDashboard": "Anasayfaya geri dön",
"cancel": "İptal",
@@ -165,6 +168,8 @@
"dark": "Karanlık",
"dashboard": "Anasayfa",
"delete": "Sil",
"deletedCountSuccessfully": "{{count}} {{label}} başarıyla silindi.",
"deletedSuccessfully": "Başarıyla silindi.",
"deleting": "Siliniyor...",
"descending": "Azalan",
"duplicate": "Çoğalt",
@@ -172,9 +177,14 @@
"edit": "Düzenle",
"editLabel": "{{label}} düzenle",
"editing": "Düzenleniyor",
"editingLabel_many": "{{count}} {{label}} düzenleniyor",
"editingLabel_one": "{{count}} {{label}} düzenleniyor",
"editingLabel_other": "{{count}} {{label}} düzenleniyor",
"email": "E-posta",
"emailAddress": "E-posta adresi",
"enterAValue": "Değer girin",
"fallbackToDefaultLocale": "Varsayılan yerel ayara geri dönme",
"filter": "Filtrele",
"filterWhere": "{{label}} filtrele:",
"filters": "Filtreler",
"globals": "Globaller",
@@ -183,8 +193,8 @@
"leaveAnyway": "Yine de ayrıl",
"leaveWithoutSaving": "Kaydetmeden ayrıl",
"light": "Aydınlık",
"locales": "Diller",
"loading": "Yükleniyor",
"locales": "Diller",
"moveDown": "Aşağı taşı",
"moveUp": "Yukarı taşı",
"newPassword": "Yeni parola",
@@ -192,6 +202,7 @@
"noLabel": "<{{label}} yok>",
"noResults": "{{label}} bulunamadı. Henüz bir {{label}} eklenmemiş olabilir veya seçtiğiniz filtrelerle eşleşen bir sonuç bulunamamış olabilir.",
"noValue": "Değer yok",
"none": "Hiç",
"notFound": "Bulunamadı",
"nothingFound": "Hiçbir şey bulunamadı",
"of": "of",
@@ -207,7 +218,9 @@
"save": "Kaydet",
"saving": "Kaydediliyor...",
"searchBy": "Şuna göre sırala: {{label}}",
"selectAll": "Tüm {{count}} {{label}}'ı seçin",
"selectValue": "Bir değer seçin",
"selectedCount": "{{count}} {{label}} seçildi",
"sorryNotFound": "Üzgünüz, isteğinizle eşleşen bir sonuç bulunamadı.",
"sort": "Sırala",
"stayOnThisPage": "Bu sayfada kal",
@@ -221,6 +234,7 @@
"unsavedChangesDuplicate": "Kaydedilmemiş değişiklikler var. Çoğaltma işlemine devam etmek istiyor musunuz?",
"untitled": "Başlıksız",
"updatedAt": "Güncellenme tarihi",
"updatedCountSuccessfully": "{{count}} {{label}} başarıyla güncellendi.",
"updatedSuccessfully": "Başarıyla güncellendi.",
"updating": "Güncelleniyor",
"uploading": "Yükleniyor",
@@ -229,18 +243,18 @@
"welcome": "Hoşgeldiniz"
},
"operators": {
"contains": "içerir",
"equals": "eşittir",
"isNotEqualTo": "eşit değildir",
"isIn": "içinde",
"isNotIn": "içinde değil",
"exists": "var",
"isGreaterThan": "şundan büyüktür",
"isGreaterThanOrEqualTo": "büyüktür veya eşittir",
"isIn": "içinde",
"isLessThan": "küçüktür",
"isLessThanOrEqualTo": "küçüktür veya eşittir",
"isGreaterThanOrEqualTo": "büyüktür veya eşittir",
"near": "yakın",
"isLike": "gibidir",
"contains": "içerir"
"isNotEqualTo": "eşit değildir",
"isNotIn": "içinde değil",
"near": "yakın"
},
"upload": {
"dragAndDrop": "Bir dosya sürükleyip bırakabilirsiniz",
@@ -256,11 +270,9 @@
"width": "Genişlik"
},
"validation": {
"fieldHasNo": "Bu alanda {{label}} girili değil.",
"requiresAtLeast": "Bu alan en az {{count}} adet {{label}} gerektirmektedir.",
"requiresNoMoreThan": "Bu alana {{count}} adetten fazla {{label}} girilemez.",
"emailAddress": "Lütfen geçerli bir e-posta adresi girin.",
"enterNumber": "Lütfen geçerli bir sayı girin.",
"fieldHasNo": "Bu alanda {{label}} girili değil.",
"greaterThanMax": "\"{{value}}\", izin verilen maksimum değerden ({{max}}) fazla.",
"invalidInput": "Bu alanda geçersiz bir giriş mevcut.",
"invalidSelection": "Bu alanda geçersiz bir seçim mevcut.",
@@ -269,45 +281,50 @@
"longerThanMin": "Bu değer minimum {{minLength}} karakterden uzun olmalıdır.",
"notValidDate": "\"{{value}}\" geçerli bir tarih değil.",
"required": "Bu alan gereklidir.",
"requiresAtLeast": "Bu alan en az {{count}} adet {{label}} gerektirmektedir.",
"requiresNoMoreThan": "Bu alana {{count}} adetten fazla {{label}} girilemez.",
"requiresTwoNumbers": "Bu alana en az iki rakam girilmesi zorunludur.",
"shorterThanMax": "Bu alan {{maxLength}} karakterden daha kısa olmalıdır.",
"trueOrFalse": "Bu alan yalnızca doğru ve yanlış olabilir.",
"validUploadID": "'Bu alan geçerli bir karşıya yükleme ID'sine sahip değil.'"
},
"version": {
"showingVersionsFor": "",
"versionCount_other": "",
"autosavedSuccessfully": "Otomatik kaydetme başarılı",
"draftSavedSuccessfully": "Taslak başarıyla kaydedildi.",
"restoredSuccessfully": "Geri getirme başarılı.",
"selectLocales": "Görüntülenecek yerel ayarları seçin",
"aboutToPublishSelection": "Seçimdeki tüm {{label}}'i yayınlamak üzeresiniz. Emin misin?",
"aboutToRestore": "Döküman {{label}}, {{versionDate}} tarihindeki sürümüne geri döndürülecek.",
"aboutToRestoreGlobal": "Global {{label}}, {{versionDate}} tarihindeki sürümüne geri döndürülecek.",
"aboutToRevertToPublished": "Bu dökümanın değişikliklerini yayınladığı haline geri getirmek üzeresiniz. Devam etmek istiyor musunuz?",
"aboutToUnpublish": "Bu dökümanı yayından kaldırmak üzeresiniz. Devam etmek istiyor musunuz?",
"aboutToUnpublishSelection": "Seçimdeki tüm {{label}} yayınını kaldırmak üzeresiniz. Emin misin?",
"autosave": "Otomatik kaydet",
"autosavedSuccessfully": "Otomatik kaydetme başarılı",
"autosavedVersion": "Otomatik kayıtlı sürüm",
"changed": "Değişiklik yapıldı",
"compareVersion": "Sürümü şununla karşılaştır:",
"confirmPublish": "Yayınlamayı onayla",
"confirmRevertToSaved": "Confirm revert to saved",
"confirmUnpublish": "Yayından kaldırmayı onayla",
"confirmVersionRestoration": "Sürümü Geri Getirmeyi Onayla",
"currentDocumentStatus": "Şu an {{docStatus}} döküman",
"draft": "Taslak",
"draftSavedSuccessfully": "Taslak başarıyla kaydedildi.",
"lastSavedAgo": "Son kaydedilme: {{distance, relativetime(minutes)}}",
"noFurtherVersionsFound": "Başka sürüm bulunamadı.",
"noRowsFound": "{{label}} bulunamadı",
"preview": "Önizleme",
"problemRestoringVersion": "Bu sürüme geri döndürürken bir hatayla karşılaşıldı.",
"publish": "Yayınla",
"publishChanges": "Değişiklikleri yayınla",
"published": "Yayınlandı",
"restoreThisVersion": "Bu sürüme geri döndür",
"restoredSuccessfully": "Geri getirme başarılı.",
"restoring": "Geri döndürülüyor...",
"revertToPublished": "Yayınlanana geri döndür",
"reverting": "Değişiklikler geri alınıyor...",
"saveDraft": "Taslağı kaydet",
"selectLocales": "Görüntülenecek yerel ayarları seçin",
"selectVersionToCompare": "Karşılaştırılacak bir sürüm seçin",
"showLocales": "Yerel ayarları göster:",
"showingVersionsFor": "Şunun için sürümler gösteriliyor:",
"status": "Durum",
"type": "Tür",
"unpublish": "Yayından Kaldır",
@@ -316,6 +333,7 @@
"versionCount_many": "{{count}} sürüm bulundu",
"versionCount_none": "Sürüm bulunamadı",
"versionCount_one": "{{count}} sürüm bulundu",
"versionCount_other": "{{count}} sürüm bulundu",
"versionCreatedOn": "{{version}} oluşturma tarihi:",
"versionID": "Sürüm ID",
"versions": "Sürümler",

View File

@@ -318,6 +318,12 @@
"unspecific": {
"type": "string"
},
"unableToDeleteCount": {
"type": "string"
},
"unableToUpdateCount": {
"type": "string"
},
"userLocked": {
"type": "string"
},
@@ -357,6 +363,8 @@
"unauthorized",
"unknown",
"unspecific",
"unableToDeleteCount",
"unableToUpdateCount",
"userLocked",
"valueMustBeUnique",
"verificationTokenInvalid"
@@ -477,6 +485,9 @@
"selectExistingLabel": {
"type": "string"
},
"selectFieldsToEdit": {
"type": "string"
},
"showAll": {
"type": "string"
},
@@ -528,6 +539,7 @@
"saveChanges",
"searchForBlock",
"selectExistingLabel",
"selectFieldsToEdit",
"showAll",
"swapUpload",
"toggleBlock",
@@ -541,6 +553,15 @@
"aboutToDelete": {
"type": "string"
},
"aboutToDeleteCount_many": {
"type": "string"
},
"aboutToDeleteCount_one": {
"type": "string"
},
"aboutToDeleteCount_other": {
"type": "string"
},
"addBelow": {
"type": "string"
},
@@ -622,6 +643,9 @@
"delete": {
"type": "string"
},
"deletedCountSuccessfully": {
"type": "string"
},
"deletedSuccessfully": {
"type": "string"
},
@@ -646,6 +670,15 @@
"editing": {
"type": "string"
},
"editingLabel_many": {
"type": "string"
},
"editingLabel_one": {
"type": "string"
},
"editingLabel_other": {
"type": "string"
},
"email": {
"type": "string"
},
@@ -760,9 +793,15 @@
"searchBy": {
"type": "string"
},
"selectAll": {
"type": "string"
},
"selectValue": {
"type": "string"
},
"selectedCount": {
"type": "string"
},
"sorryNotFound": {
"type": "string"
},
@@ -802,6 +841,9 @@
"updatedAt": {
"type": "string"
},
"updatedCountSuccessfully": {
"type": "string"
},
"updatedSuccessfully": {
"type": "string"
},
@@ -823,6 +865,9 @@
},
"required": [
"aboutToDelete",
"aboutToDeleteCount_many",
"aboutToDeleteCount_one",
"aboutToDeleteCount_other",
"addBelow",
"addFilter",
"adminTheme",
@@ -849,6 +894,7 @@
"dark",
"dashboard",
"delete",
"deletedCountSuccessfully",
"deletedSuccessfully",
"deleting",
"descending",
@@ -856,6 +902,9 @@
"duplicateWithoutSaving",
"editLabel",
"editing",
"editingLabel_many",
"editingLabel_one",
"editingLabel_other",
"email",
"emailAddress",
"enterAValue",
@@ -893,7 +942,9 @@
"save",
"saving",
"searchBy",
"selectAll",
"selectValue",
"selectedCount",
"sorryNotFound",
"sort",
"stayOnThisPage",
@@ -907,6 +958,7 @@
"unsavedChangesDuplicate",
"untitled",
"updatedAt",
"updatedCountSuccessfully",
"updatedSuccessfully",
"user",
"users",
@@ -1101,6 +1153,9 @@
"type": "object",
"additionalProperties": false,
"properties": {
"aboutToPublishSelection": {
"type": "string"
},
"aboutToRestore": {
"type": "string"
},
@@ -1113,6 +1168,9 @@
"aboutToUnpublish": {
"type": "string"
},
"aboutToUnpublishSelection": {
"type": "string"
},
"autosave": {
"type": "string"
},
@@ -1128,6 +1186,9 @@
"compareVersion": {
"type": "string"
},
"confirmPublish": {
"type": "string"
},
"confirmRevertToSaved": {
"type": "string"
},
@@ -1164,6 +1225,9 @@
"publishChanges": {
"type": "string"
},
"publish": {
"type": "string"
},
"published": {
"type": "string"
},
@@ -1247,15 +1311,18 @@
}
},
"required": [
"aboutToPublishSelection",
"aboutToRestore",
"aboutToRestoreGlobal",
"aboutToRevertToPublished",
"aboutToUnpublish",
"aboutToUnpublishSelection",
"autosave",
"autosavedSuccessfully",
"autosavedVersion",
"changed",
"compareVersion",
"confirmPublish",
"confirmRevertToSaved",
"confirmUnpublish",
"confirmVersionRestoration",
@@ -1268,6 +1335,7 @@
"preview",
"problemRestoringVersion",
"publishChanges",
"publish",
"published",
"restoreThisVersion",
"restoredSuccessfully",

View File

@@ -82,6 +82,8 @@
"problemUploadingFile": "Виникла помилка під час завантаження файлу.",
"tokenInvalidOrExpired": "Токен або не дійсний, або його строк дії закінчився.",
"unPublishingDocument": "Підчас відміни публікації даного документа, виникла помилка.",
"unableToDeleteCount": "Не вдалося видалити {{count}} із {{total}} {{label}}.",
"unableToUpdateCount": "Не вдалося оновити {{count}} із {{total}} {{label}}.",
"unauthorized": "Немає доступу, ви повинні увійти, щоб виконати цей запит.",
"unknown": "Виникла невідома помилка.",
"unspecific": "Виникла помилка.",
@@ -123,6 +125,7 @@
"saveChanges": "Зберегти зміни",
"searchForBlock": "Знайти блок",
"selectExistingLabel": "Вибрати існуючий {{label}}",
"selectFieldsToEdit": "Виберіть поля для редагування",
"showAll": "Показати все",
"swapUpload": "Замінити завантаження",
"textToDisplay": "Текст для відображення",
@@ -131,6 +134,9 @@
},
"general": {
"aboutToDelete": "Ви бажаєте видалити {{label}} <1>{{title}}</1>. Ви впевнені?",
"aboutToDeleteCount_many": "Ви збираєтеся видалити {{count}} {{label}}",
"aboutToDeleteCount_one": "Ви збираєтеся видалити {{count}} {{label}}",
"aboutToDeleteCount_other": "Ви збираєтеся видалити {{count}} {{label}}",
"addBelow": "Добавити нижче",
"addFilter": "Добавити фільтр",
"adminTheme": "Тема адмінки",
@@ -158,6 +164,7 @@
"dark": "Темна",
"dashboard": "Головна",
"delete": "Видалити",
"deletedCountSuccessfully": "Успішно видалено {{count}} {{label}}.",
"deletedSuccessfully": "Успішно видалено.",
"deleting": "Видалення...",
"descending": "В порядку спадання",
@@ -166,6 +173,9 @@
"edit": "Редагувати",
"editLabel": "Редагувати {{label}}",
"editing": "Редагування",
"editingLabel_many": "Редагування {{count}} {{label}}",
"editingLabel_one": "Редагування {{count}} {{label}}",
"editingLabel_other": "Редагування {{count}} {{label}}",
"email": "Email",
"emailAddress": "Email адреса",
"enterAValue": "Введіть значення",
@@ -204,7 +214,9 @@
"save": "Зберегти",
"saving": "Збереження...",
"searchBy": "Шукати по {{label}}",
"selectAll": "Вибрати всі {{count}} {{label}}",
"selectValue": "Вибрати значення",
"selectedCount": "Вибрано {{count}} {{label}}",
"sorryNotFound": "Вибачте - немає нічого, що відповідало б Вашому запиту.",
"sort": "Сортувати",
"stayOnThisPage": "Залишитись на цій сторінці",
@@ -218,6 +230,7 @@
"unsavedChangesDuplicate": "Ви маєте не збережені зміни. Чи бажаєте ви продовжити дублювання?",
"untitled": "Без назви",
"updatedAt": "Змінено",
"updatedCountSuccessfully": "Успішно оновлено {{count}} {{label}}.",
"updatedSuccessfully": "Успішно відредаговано.",
"updating": "оновлення",
"uploading": "завантаження",
@@ -226,20 +239,21 @@
"welcome": "Вітаю"
},
"operators": {
"contains": "містить",
"equals": "дорівнює",
"isNotEqualTo": "не дорівнює",
"isIn": "є в",
"isNotIn": "не в",
"exists": "існує",
"isGreaterThan": "більше ніж",
"isGreaterThanOrEqualTo": "більше або дорівнює",
"isIn": "є в",
"isLessThan": "менше ніж",
"isLessThanOrEqualTo": "менше або дорівнює",
"isGreaterThanOrEqualTo": "більше або дорівнює",
"near": "поруч",
"isLike": "схоже",
"contains": "містить"
"isNotEqualTo": "не дорівнює",
"isNotIn": "не в",
"near": "поруч"
},
"upload": {
"dragAndDrop": "Перемістіть файл",
"dragAndDropHere": "або перемістіть сюди файл",
"fileName": "Назва файлу",
"fileSize": "Розмір файлу",
@@ -248,7 +262,6 @@
"moreInfo": "Більше інформації",
"selectCollectionToBrowse": "Виберіть колекцію для перегляду",
"selectFile": "Виберіть файл",
"dragAndDrop": "Перемістіть файл",
"sizes": "Розміри",
"width": "Ширина"
},
@@ -272,15 +285,18 @@
"validUploadID": "Це поле не є дійсним ID завантаження."
},
"version": {
"aboutToPublishSelection": "Ви збираєтеся опублікувати всі {{label}} у добірці. Ти впевнений?",
"aboutToRestore": "Ви збираєтесь відновити цей документ {{label}} до стану, в якому він знаходився {{versionDate}}.",
"aboutToRestoreGlobal": "Ви збираєтесь відновити глобальний запис {{label}} до стану, в якому він знаходився {{versionDate}}.",
"aboutToRevertToPublished": "Ви збираєтесь вернути зміни цього документа до його опублікованого стану. Ви впевнені?",
"aboutToUnpublish": "Ви збираєтесь відмінити публікацю цього документа. Ви впевнені?",
"aboutToUnpublishSelection": "Ви збираєтеся скасувати публікацію всіх {{label}} у вибраному. Ти впевнений?",
"autosave": "Автозбереження",
"autosavedSuccessfully": "Автозбереження успішно виконано.",
"autosavedVersion": "Автозбережена версія",
"changed": "Змінено",
"compareVersion": "Порівняти версію з:",
"confirmPublish": "Підтвердити публікацію",
"confirmRevertToSaved": "Підтвердити повернення до збереженого",
"confirmUnpublish": "Підвтердити відміну публікації",
"confirmVersionRestoration": "Підтвердити відновлення версії",
@@ -292,6 +308,7 @@
"noRowsFound": "Не знайдено {{label}}",
"preview": "Попередній перегляд",
"problemRestoringVersion": "Виникла проблема з відновленням цієї версії",
"publish": "Опублікувати",
"publishChanges": "Опублікувати зміни",
"published": "Опубліковано",
"restoreThisVersion": "Відновити цю версію",
@@ -302,8 +319,8 @@
"saveDraft": "Зберегти чернетку",
"selectLocales": "Виберіть переклад для відображення",
"selectVersionToCompare": "Виберіть версію для порівняння",
"showingVersionsFor": "Показані версії для:",
"showLocales": "Показати переклади:",
"showingVersionsFor": "Показані версії для:",
"status": "Статус",
"type": "Тип",
"unpublish": "Відмінити публікацію",

View File

@@ -60,8 +60,8 @@
"accountAlreadyActivated": "Lỗi - Tài khoản này đã được kích hoạt.",
"autosaving": "Lỗi - Đã xảy ra vấn đề khi tự động sao lưu bản tài liệu này.",
"correctInvalidFields": "Lỗi - Xin hãy sửa lại những fields không hợp lệ.",
"deletingTitle": "Lỗi - Đã xảy ra vấn đề khi xóa {{title}}. Hãy kiểm tra kết nối mạng và thử lại.",
"deletingFile": "Lỗi - Đã xảy ra vấn đề khi xóa file này.",
"deletingTitle": "Lỗi - Đã xảy ra vấn đề khi xóa {{title}}. Hãy kiểm tra kết nối mạng và thử lại.",
"emailOrPasswordIncorrect": "Lỗi - Email hoặc mật khẩu không chính xác.",
"followingFieldsInvalid_many": "Lỗi - Những fields sau không hợp lệ:",
"followingFieldsInvalid_one": "Lỗi - Field sau không hợp lệ:",
@@ -82,6 +82,8 @@
"problemUploadingFile": "Lỗi - Đã xảy ra vấn để khi tải lên file sau.",
"tokenInvalidOrExpired": "Lỗi - Token không hợp lệ hoặc đã hết hạn.",
"unPublishingDocument": "Lỗi - Đã xảy ra vấn để khi ẩn bản tài liệu.",
"unableToDeleteCount": "Không thể xóa {{count}} trong số {{total}} {{label}}.",
"unableToUpdateCount": "Không thể cập nhật {{count}} trên {{total}} {{label}}.",
"unauthorized": "Lỗi - Bạn cần phải đăng nhập trước khi gửi request sau.",
"unknown": "Lỗi - Không xác định (unknown error).",
"unspecific": "Lỗi - Đã xảy ra (unspecific error).",
@@ -90,47 +92,59 @@
"verificationTokenInvalid": "Lỗi - Token dùng để xác thực không hợp lệ."
},
"fields": {
"block": "block",
"blocks": "blocks",
"addLabel": "Thêm: {{label}}",
"addLink": "Thêm liên kết",
"addNew": "Thêm mới",
"addNewLabel": "Thêm mới: {{label}}",
"addRelationship": "Thêm mối quan hệ (relationship)",
"addUpload": "Thêm tải lên (upload)",
"block": "block",
"blockType": "Block Type",
"blocks": "blocks",
"chooseBetweenCustomTextOrDocument": "Chọn giữa nhập URL văn bản tùy chỉnh hoặc liên kết đến tài liệu khác.",
"chooseDocumentToLink": "Chọn một tài liệu để liên kết đến",
"chooseFromExisting": "Chọn từ vật phẩm có sẵn",
"chooseLabel": "Chọn: {{label}}",
"collapseAll": "Ẩn toàn bộ",
"customURL": "URL tùy chỉnh",
"editLabelData": "Chỉnh sửa nội dung của: {{label}}",
"editLink": "Chỉnh sửa liên kết",
"editRelationship": "Chỉnh sửa mối quan hệ",
"enterURL": "Nhập một URL",
"internalLink": "Liên kết nội bộ",
"itemsAndMore": "{{items}} và {{count}} món nữa",
"labelRelationship": "Mối quan hệ của {{label}} (Relationship)",
"latitude": "Vĩ độ",
"linkType": "Loại liên kết",
"linkedTo": "Được nối với <0>{{label}}</0>",
"longitude": "Kinh độ",
"newLabel": "Tạo {{label}} mới",
"openInNewTab": "Mở ra trong trang mới",
"passwordsDoNotMatch": "Mật khẩu không trùng.",
"relatedDocument": "bản tài liệu liên quan",
"relationTo": "Có quan hệ với",
"removeReelationship": "Xóa mối quan hệ",
"removeUpload": "Xóa bản tải lên",
"saveChanges": "Luu thay đổi",
"searchForBlock": "Tìm block",
"selectExistingLabel": "Chọn một {{label}} có sẵn",
"selectFieldsToEdit": "Chọn các trường để chỉnh sửa",
"showAll": "Hiển thị toàn bộ",
"swapRelationship": "Hoán đổi quan hệ",
"swapUpload": "Đổi bản tải lên",
"textToDisplay": "Văn bản để hiển thị",
"toggleBlock": "Bật/tắt block",
"uploadNewLabel": "Tải lên bản mới: {{label}}"
},
"general": {
"aboutToDelete": "Chuẩn bị xóa {{label}} <1>{{title}}</1>. Bạn có muốn tiếp tục không?",
"aboutToDeleteCount_many": "Bạn sắp xóa {{count}} {{label}}",
"aboutToDeleteCount_one": "Bạn sắp xóa {{count}} {{label}}",
"aboutToDeleteCount_other": "Bạn sắp xóa {{count}} {{label}}",
"addBelow": "Thêm bên dưới",
"addFilter": "Thêm bộ lọc",
"adminTheme": "Phông nền của trang Admin",
"and": "Và",
"ascending": "Sắp xếp theo thứ tự tăng dần",
"automatic": "Tự động",
"backToDashboard": "Quay lại bảng điều khiển",
"cancel": "Ngừng thao tác",
@@ -153,6 +167,7 @@
"dark": "Nền tối",
"dashboard": "Bảng điều khiển",
"delete": "Xóa",
"deletedCountSuccessfully": "Đã xóa thành công {{count}} {{label}}.",
"deletedSuccessfully": "Đã xoá thành công.",
"deleting": "Đang xóa...",
"descending": "Xếp theo thứ tự giảm dần",
@@ -161,6 +176,9 @@
"edit": "Chỉnh sửa",
"editLabel": "Chỉnh sửa: {{label}}",
"editing": "Đang chỉnh sửa",
"editingLabel_many": "Đang chỉnh sửa {{count}} {{label}}",
"editingLabel_one": "Đang chỉnh sửa {{count}} {{label}}",
"editingLabel_other": "Đang chỉnh sửa {{count}} {{label}}",
"email": "Email",
"emailAddress": "Địa chỉ Email",
"enterAValue": "Nhập một giá trị",
@@ -199,7 +217,9 @@
"save": "Luu",
"saving": "Đang lưu...",
"searchBy": "Tìm với {{label}}",
"selectAll": "Chọn tất cả {{count}} {{label}}",
"selectValue": "Chọn một giá trị",
"selectedCount": "Đã chọn {{count}} {{nhãn}}",
"sorryNotFound": "Xin lỗi, không có kết quả nào tương ứng với request của bạn.",
"sort": "Sắp xếp",
"stayOnThisPage": "Ở lại trang này",
@@ -213,6 +233,7 @@
"unsavedChangesDuplicate": "Bạn chưa lưu các thay đổi. Bạn có muốn tiếp tục tạo bản sao?",
"untitled": "Không tiêu đề",
"updatedAt": "Được cập nhật vào lúc",
"updatedCountSuccessfully": "Đã cập nhật thành công {{count}} {{label}}.",
"updatedSuccessfully": "Cập nhật thành công.",
"updating": "Đang cập nhật",
"uploading": "Đang tải lên",
@@ -221,20 +242,21 @@
"welcome": "Xin chào"
},
"operators": {
"contains": "chứa",
"equals": "bằng",
"isNotEqualTo": "không bằng",
"isIn": "đang ở",
"isNotIn": "không có trong",
"exists": "tồn tại",
"isGreaterThan": "lớn hơn",
"isGreaterThanOrEqualTo": "lớn hơn hoặc bằng",
"isIn": "đang ở",
"isLessThan": "nhỏ hơn",
"isLessThanOrEqualTo": "nhỏ hơn hoặc bằng",
"isGreaterThanOrEqualTo": "lớn hơn hoặc bằng",
"near": "gần",
"isLike": "giống như",
"contains": "chứa"
"isNotEqualTo": "không bằng",
"isNotIn": "không có trong",
"near": "gần"
},
"upload": {
"dragAndDrop": "Kéo và thả một tập tin",
"dragAndDropHere": "hoặc kéo và thả file vào đây",
"fileName": "Tên file",
"fileSize": "Dung lượng file",
@@ -243,7 +265,6 @@
"moreInfo": "Hiển thị nhiều hơn",
"selectCollectionToBrowse": "Chọn một Collection để tìm",
"selectFile": "Chọn một file",
"dragAndDrop": "Kéo và thả một tập tin",
"sizes": "Các độ phân giải",
"width": "Chiều rộng"
},
@@ -267,15 +288,18 @@
"validUploadID": "'Field này không chứa ID tải lên hợp lệ.'"
},
"version": {
"aboutToPublishSelection": "Bạn sắp xuất bản tất cả {{nhãn}} trong lựa chọn. Bạn có chắc không?",
"aboutToRestore": "Bạn chuẩn bị khôi phục lại {{label}} về trạng thái mà bản tài liệu này sở hữu lúc {{versionDate}}.",
"aboutToRestoreGlobal": "Bạn chuẩn bị khôi phục lại bản toàn thể (global) của {{label}} về trạng thái mà bản tài liệu này sở hữu lúc {{versionDate}}.",
"aboutToRevertToPublished": "Bạn chuẩn bị khiến bản nháp này quay về trạng thái khi được xuất bản. Bạn có muốn tiếp tục không?",
"aboutToUnpublish": "Bạn chuẩn bị ẩn bản tài liệu này. Bạn chắc chứ?",
"aboutToUnpublishSelection": "Bạn sắp hủy xuất bản tất cả {{nhãn}} trong lựa chọn. Bạn có chắc không?",
"autosave": "Tự động lưu dữ liệu",
"autosavedSuccessfully": "Đã tự động lưu thành công.",
"autosavedVersion": "Các phiên bản từ việc tự động lưu dữ liệu",
"changed": "Đã đổi",
"compareVersion": "So sánh phiên bản này với:",
"confirmPublish": "xác nhận xuất bản",
"confirmRevertToSaved": "Xác nhận, quay về trạng thái đã lưu",
"confirmUnpublish": "Xác nhận, ẩn tài liệu",
"confirmVersionRestoration": "Xác nhận, khôi phục về phiên bản sau",
@@ -287,6 +311,7 @@
"noRowsFound": "Không tìm thấy: {{label}}",
"preview": "Bản xem trước",
"problemRestoringVersion": "Đã xảy ra vấn đề khi khôi phục phiên bản này",
"publish": "Công bố",
"publishChanges": "Xuất bản tài liệu",
"published": "Đã xuất bản",
"restoreThisVersion": "Khôi phục về phiên bản này",
@@ -298,6 +323,7 @@
"selectLocales": "Chọn mã khu vực để hiện thị",
"selectVersionToCompare": "Chọn phiên bản để so sánh",
"showLocales": "Hiển thị mã khu vực:",
"showingVersionsFor": "Hiển thị các phiên bản cho:",
"status": "Trạng thái",
"type": "Loại",
"unpublish": "Ẩn tài liệu",
@@ -306,6 +332,7 @@
"versionCount_many": "{{count}} phiên bản được tìm thấy",
"versionCount_none": "Không có phiên bản nào được tìm thấy",
"versionCount_one": "{{count}} phiên bản được tìm thấy",
"versionCount_other": "Đã tìm thấy {{count}} phiên bản",
"versionCreatedOn": "Phiên bản {{version}} được tạo vào lúc:",
"versionID": "ID của phiên bản",
"versions": "Những phiên bản",

View File

@@ -82,6 +82,8 @@
"problemUploadingFile": "上传文件时出现了问题。",
"tokenInvalidOrExpired": "令牌无效或已过期。",
"unPublishingDocument": "取消发布此文件时出现了问题。",
"unableToDeleteCount": "无法从 {{total}} {{label}} 中删除 {{count}}。",
"unableToUpdateCount": "无法更新 {{count}} 个,共 {{total}} 个 {{label}}。",
"unauthorized": "未经授权,您必须登录才能提出这个请求。",
"unknown": "发生了一个未知的错误。",
"unspecific": "发生了一个错误。",
@@ -126,6 +128,7 @@
"saveChanges": "保存更改",
"searchForBlock": "搜索一个区块",
"selectExistingLabel": "选择现有的{{label}}",
"selectFieldsToEdit": "选择要编辑的字段",
"showAll": "显示全部",
"swapRelationship": "交换关系",
"swapUpload": "交换上传",
@@ -135,6 +138,9 @@
},
"general": {
"aboutToDelete": "您即将删除{{label}} <1>{{title}}</1>。您确定要继续吗?",
"aboutToDeleteCount_many": "您即将删除 {{count}} {{label}}",
"aboutToDeleteCount_one": "您即将删除 {{count}} {{label}}",
"aboutToDeleteCount_other": "您即将删除 {{count}} {{label}}",
"addBelow": "添加到下面",
"addFilter": "添加过滤器",
"adminTheme": "管理页面主题",
@@ -162,6 +168,7 @@
"dark": "深色",
"dashboard": "仪表板",
"delete": "删除",
"deletedCountSuccessfully": "已成功删除 {{count}} {{label}}。",
"deletedSuccessfully": "已成功删除。",
"deleting": "删除中...",
"descending": "降序",
@@ -170,6 +177,9 @@
"edit": "编辑",
"editLabel": "编辑{{label}}",
"editing": "编辑中",
"editingLabel_many": "编辑 {{count}} {{label}}",
"editingLabel_one": "编辑 {{count}} {{label}}",
"editingLabel_other": "编辑 {{count}} {{label}}",
"email": "电子邮件",
"emailAddress": "电子邮件地址",
"enterAValue": "输入一个值",
@@ -208,7 +218,9 @@
"save": "保存",
"saving": "保存中...",
"searchBy": "搜索{{label}}",
"selectAll": "选择所有 {{count}} {{label}}",
"selectValue": "选择一个值",
"selectedCount": "已选择 {{count}} {{label}}",
"sorryNotFound": "对不起,没有与您的请求相对应的东西。",
"sort": "排序",
"stayOnThisPage": "停留在此页面",
@@ -222,26 +234,28 @@
"unsavedChangesDuplicate": "您有未保存的修改。您确定要继续重复吗?",
"untitled": "无标题",
"updatedAt": "更新于",
"updatedCountSuccessfully": "已成功更新 {{count}} {{label}}。",
"updatedSuccessfully": "更新成功。",
"user": "用户",
"users": "用户",
"welcome": "欢迎"
},
"operators": {
"contains": "包含",
"equals": "等于",
"isNotEqualTo": "不等于",
"isIn": "在",
"isNotIn": "不在",
"exists": "存在",
"isGreaterThan": "大于",
"isGreaterThanOrEqualTo": "大于等于",
"isIn": "在",
"isLessThan": "小于",
"isLessThanOrEqualTo": "小于或等于",
"isGreaterThanOrEqualTo": "大于等于",
"near": "附近",
"isLike": "就像",
"contains": "包含"
"isNotEqualTo": "不等于",
"isNotIn": "不在",
"near": "附近"
},
"upload": {
"dragAndDrop": "拖放一个文件",
"dragAndDropHere": "或在这里拖放一个文件",
"fileName": "文件名",
"fileSize": "文件大小",
@@ -250,7 +264,6 @@
"moreInfo": "更多信息",
"selectCollectionToBrowse": "选择一个要浏览的集合",
"selectFile": "选择一个文件",
"dragAndDrop": "拖放一个文件",
"sizes": "尺寸",
"width": "宽度"
},
@@ -274,15 +287,18 @@
"validUploadID": "该字段不是有效的上传ID。"
},
"version": {
"aboutToPublishSelection": "您即将发布所选内容中的所有 {{label}}。 你确定吗?",
"aboutToRestore": "您将把这个{{label}}文档恢复到{{versionDate}}时的状态",
"aboutToRestoreGlobal": "您要将全局的{{label}}恢复到{{versionDate}}时的状态",
"aboutToRevertToPublished": "您将要把这个文档的内容还原到它的发布状态。您确定吗?",
"aboutToUnpublish": "你即将取消发布这个文档。你确定吗?",
"aboutToUnpublishSelection": "您即将取消发布所选内容中的所有 {{label}}。 你确定吗?",
"autosave": "自动保存",
"autosavedSuccessfully": "自动保存成功。",
"autosavedVersion": "自动保存的版本",
"changed": "已更改",
"compareVersion": "对比版本:",
"confirmPublish": "确认发布",
"confirmRevertToSaved": "确认恢复到保存状态",
"confirmUnpublish": "确认取消发布",
"confirmVersionRestoration": "确认版本恢复",
@@ -294,6 +310,7 @@
"noRowsFound": "没有发现{{label}}",
"preview": "预览",
"problemRestoringVersion": "恢复这个版本时发生了问题",
"publish": "发布",
"publishChanges": "发布修改",
"published": "已发布",
"restoreThisVersion": "恢复此版本",
@@ -304,8 +321,8 @@
"saveDraft": "保存草稿",
"selectLocales": "选择要显示的语言",
"selectVersionToCompare": "选择要比较的版本",
"showingVersionsFor": "显示版本为:",
"showLocales": "显示语言:",
"showingVersionsFor": "显示版本为:",
"status": "状态",
"type": "类型",
"unpublish": "取消发布",

View File

@@ -0,0 +1,56 @@
import path from 'path';
import fs from 'fs';
import type { TFunction } from 'i18next';
import fileExists from './fileExists';
import { ErrorDeletingFile } from '../errors';
import type { FileData, FileToSave } from './types';
import type { SanitizedConfig } from '../config/types';
import type { SanitizedCollectionConfig } from '../collections/config/types';
type Args = {
config: SanitizedConfig
collectionConfig: SanitizedCollectionConfig
files?: FileToSave[]
doc: Record<string, unknown>
t: TFunction
overrideDelete: boolean
}
export const deleteAssociatedFiles: (args: Args) => Promise<void> = async ({
config,
collectionConfig,
files = [],
doc,
t,
overrideDelete,
}) => {
if (!collectionConfig.upload) return;
if (overrideDelete || files.length > 0) {
const { staticDir } = collectionConfig.upload;
const staticPath = path.resolve(config.paths.configDir, staticDir);
const fileToDelete = `${staticPath}/${doc.filename}`;
if (await fileExists(fileToDelete)) {
fs.unlink(fileToDelete, (err) => {
if (err) {
throw new ErrorDeletingFile(t);
}
});
}
if (doc.sizes) {
Object.values(doc.sizes)
.forEach(async (size: FileData) => {
const sizeToDelete = `${staticPath}/${size.filename}`;
if (await fileExists(sizeToDelete)) {
fs.unlink(sizeToDelete, (err) => {
if (err) {
throw new ErrorDeletingFile(t);
}
});
}
});
}
}
};

View File

@@ -74,6 +74,7 @@ const getBaseUploadFields = ({ config, collection }: Options): Field[] => {
admin: {
readOnly: true,
hidden: true,
disableBulkEdit: true,
},
};

View File

@@ -0,0 +1,33 @@
import fs from 'fs';
import { promisify } from 'util';
import { mapAsync } from '../utilities/mapAsync';
import type { PayloadRequest } from '../express/types';
import type { SanitizedConfig } from '../config/types';
import type { SanitizedCollectionConfig } from '../collections/config/types';
const unlinkFile = promisify(fs.unlink);
type Args = {
req: PayloadRequest
config: SanitizedConfig
collectionConfig: SanitizedCollectionConfig
}
/**
* Remove temp files if enabled, as express-fileupload does not do this automatically
*/
export const unlinkTempFiles: (args: Args) => Promise<void> = async ({
req,
config,
collectionConfig,
}) => {
if (config.upload?.useTempFiles && collectionConfig.upload) {
const { files } = req;
const fileArray = Array.isArray(files) ? files : [files];
await mapAsync(fileArray, async ({ file }) => {
// Still need this check because this will not be populated if using local API
if (file.tempFilePath) {
await unlinkFile(file.tempFilePath);
}
});
}
};

View File

@@ -22,6 +22,7 @@ const baseVersionFields: Field[] = [
options: statuses,
defaultValue: 'draft',
admin: {
disableBulkEdit: true,
components: {
Field: () => null,
},

View File

@@ -18,7 +18,7 @@ type Args = {
accessResult: AccessResult
collection: Collection
locale: string
paginationOptions: PaginateOptions
paginationOptions?: PaginateOptions
payload: Payload
where: Where
}
@@ -69,25 +69,32 @@ export const queryDrafts = async <T extends TypeWithID>({
allowDiskUse: true,
});
const aggregatePaginateOptions = {
...paginationOptions,
useFacet: payload.mongoOptions?.useFacet,
sort: Object.entries(paginationOptions.sort).reduce((sort, [incomingSortKey, order]) => {
let key = incomingSortKey;
let result;
if (!['createdAt', 'updatedAt', '_id'].includes(incomingSortKey)) {
key = `version.${incomingSortKey}`
}
if (paginationOptions) {
const aggregatePaginateOptions = {
...paginationOptions,
useFacet: payload.mongoOptions?.useFacet,
sort: Object.entries(paginationOptions.sort)
.reduce((sort, [incomingSortKey, order]) => {
let key = incomingSortKey;
return {
...sort,
[key]: order === 'asc' ? 1 : -1,
};
}, {})
if (!['createdAt', 'updatedAt', '_id'].includes(incomingSortKey)) {
key = `version.${incomingSortKey}`;
}
return {
...sort,
[key]: order === 'asc' ? 1 : -1,
};
}, {}),
};
result = await VersionModel.aggregatePaginate(aggregate, aggregatePaginateOptions);
} else {
result = aggregate.exec();
}
const result = await VersionModel.aggregatePaginate(aggregate, aggregatePaginateOptions);
return {
...result,
docs: result.docs.map((doc) => ({