apostrophe 4.12.0 → 4.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/lib/moog.js +8 -0
  3. package/modules/@apostrophecms/area/ui/apos/components/AposAreaExpandedMenu.vue +10 -1
  4. package/modules/@apostrophecms/attachment/index.js +5 -1
  5. package/modules/@apostrophecms/color-field/ui/apos/components/AposColor.vue +4 -10
  6. package/modules/@apostrophecms/color-field/ui/apos/lib/AposColorAlpha.vue +2 -7
  7. package/modules/@apostrophecms/color-field/ui/apos/lib/AposColorHue.vue +1 -1
  8. package/modules/@apostrophecms/color-field/ui/apos/lib/AposColorSaturation.vue +1 -1
  9. package/modules/@apostrophecms/doc-type/index.js +3 -1
  10. package/modules/@apostrophecms/file/index.js +7 -1
  11. package/modules/@apostrophecms/file-tag/index.js +1 -0
  12. package/modules/@apostrophecms/http/lib/big-upload-middleware.js +34 -34
  13. package/{lib → modules/@apostrophecms/http/ui/apos}/big-upload-client.js +18 -4
  14. package/modules/@apostrophecms/http/ui/apos/package.json +4 -0
  15. package/modules/@apostrophecms/i18n/i18n/de.json +40 -20
  16. package/modules/@apostrophecms/i18n/i18n/en.json +37 -19
  17. package/modules/@apostrophecms/i18n/i18n/es.json +39 -19
  18. package/modules/@apostrophecms/i18n/i18n/fr.json +39 -19
  19. package/modules/@apostrophecms/i18n/i18n/it.json +39 -19
  20. package/modules/@apostrophecms/i18n/i18n/pt-BR.json +40 -20
  21. package/modules/@apostrophecms/i18n/i18n/sk.json +39 -19
  22. package/modules/@apostrophecms/i18n/index.js +397 -0
  23. package/modules/@apostrophecms/i18n/ui/apos/apps/AposI18nBatchReporting.js +161 -0
  24. package/modules/@apostrophecms/i18n/ui/apos/components/AposI18nLocalize.vue +274 -52
  25. package/modules/@apostrophecms/image/index.js +1 -0
  26. package/modules/@apostrophecms/image/ui/apos/components/AposMediaManager.vue +78 -20
  27. package/modules/@apostrophecms/image-tag/index.js +1 -0
  28. package/modules/@apostrophecms/job/index.js +1 -2
  29. package/modules/@apostrophecms/login/ui/apos/components/TheAposLogin.vue +2 -2
  30. package/modules/@apostrophecms/login/ui/apos/components/TheAposLoginHeader.vue +1 -0
  31. package/modules/@apostrophecms/modal/index.js +2 -1
  32. package/modules/@apostrophecms/modal/ui/apos/apps/AposModals.js +1 -0
  33. package/modules/@apostrophecms/modal/ui/apos/components/AposDocsManagerToolbar.vue +8 -1
  34. package/modules/@apostrophecms/modal/ui/apos/components/AposModalBody.vue +4 -0
  35. package/modules/@apostrophecms/modal/ui/apos/components/AposModalReport.vue +414 -0
  36. package/modules/@apostrophecms/module/index.js +1 -0
  37. package/modules/@apostrophecms/notification/index.js +8 -13
  38. package/modules/@apostrophecms/notification/ui/apos/apps/AposNotification.js +5 -0
  39. package/modules/@apostrophecms/notification/ui/apos/components/AposNotification.vue +110 -152
  40. package/modules/@apostrophecms/notification/ui/apos/components/TheAposNotifications.vue +10 -91
  41. package/modules/@apostrophecms/page/index.js +24 -1
  42. package/modules/@apostrophecms/piece-type/index.js +33 -2
  43. package/modules/@apostrophecms/piece-type/ui/apos/components/AposUtilityOperations.vue +1 -0
  44. package/modules/@apostrophecms/rich-text-widget/index.js +14 -0
  45. package/modules/@apostrophecms/rich-text-widget/lib/apiRoutes.js +51 -0
  46. package/modules/@apostrophecms/rich-text-widget/lib/generateTiptapTable.js +36 -0
  47. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposImageControlDialog.vue +40 -83
  48. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposRichTextWidgetEditor.vue +35 -144
  49. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposTiptapAnchor.vue +55 -84
  50. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposTiptapColor.vue +129 -168
  51. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposTiptapImage.vue +31 -42
  52. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposTiptapImportTable.vue +92 -0
  53. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposTiptapInsertBtn.vue +78 -0
  54. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposTiptapInsertItem.vue +142 -0
  55. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposTiptapLink.vue +72 -102
  56. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposTiptapMarks.vue +31 -36
  57. package/modules/@apostrophecms/schema/index.js +13 -0
  58. package/modules/@apostrophecms/schema/ui/apos/logic/AposArrayEditor.js +25 -21
  59. package/modules/@apostrophecms/template/views/outerLayoutBase.html +1 -1
  60. package/modules/@apostrophecms/ui/ui/apos/components/AposButton.vue +3 -2
  61. package/modules/@apostrophecms/ui/ui/apos/components/AposColorCheckerboard.vue +20 -0
  62. package/modules/@apostrophecms/ui/ui/apos/components/AposContextMenu.vue +104 -45
  63. package/modules/@apostrophecms/ui/ui/apos/components/AposContextMenuDialog.vue +1 -3
  64. package/modules/@apostrophecms/ui/ui/apos/components/AposTable.vue +359 -0
  65. package/modules/@apostrophecms/ui/ui/apos/scss/global/_theme.scss +4 -0
  66. package/modules/@apostrophecms/ui/ui/apos/scss/global/_utilities.scss +1 -1
  67. package/modules/@apostrophecms/ui/ui/apos/scss/global/_widgets.scss +1 -1
  68. package/modules/@apostrophecms/ui/ui/apos/scss/mixins/_zindex.scss +2 -2
  69. package/modules/@apostrophecms/ui/ui/apos/stores/modal.js +13 -0
  70. package/modules/@apostrophecms/ui/ui/apos/stores/notification.js +204 -0
  71. package/modules/@apostrophecms/ui/ui/apos/utils/index.js +73 -2
  72. package/modules/@apostrophecms/user/index.js +1 -0
  73. package/package.json +2 -1
  74. package/test/big-upload.js +3 -4
  75. package/test/i18n-batch.js +568 -0
  76. package/test/i18n.js +26 -0
  77. package/test/modules/i18n-test-page/views/page.html +3 -0
  78. package/test/moog.js +47 -0
  79. package/test/relationships.js +21 -3
  80. package/test/utils.js +32 -1
  81. package/modules/@apostrophecms/color-field/ui/apos/lib/AposColorCheckerboard.vue +0 -90
  82. package/modules/@apostrophecms/i18n/ui/apos/components/AposI18nLocalizeErrors.vue +0 -154
package/CHANGELOG.md CHANGED
@@ -1,5 +1,62 @@
1
1
  # Changelog
2
2
 
3
+ ## 4.14.0 (2025-03-19)
4
+
5
+ ### Adds
6
+
7
+ * Add a label for the `@apostrophecms/attachment` module (error reporting reasons).
8
+ * Add `translate` boolean option for report modal header configuration to force translation of the relevant items value (table cells).
9
+ * Adds feature to generate a table from an imported CSV file inside the rich-text-widget.
10
+ * Add data-test attributes to the login page.
11
+ * Adds AI-generated missing translations
12
+ * Adds the missing "Tags" filter to the chooser/manager view of files.
13
+
14
+ ### Changes
15
+
16
+ * Bumps the `perPage` option for piece-types from 10 to 50
17
+ * Reworks rich text popovers to use `AposContextMenu`, for toolbar components as well as insert menu items.
18
+
19
+ ### Fixes
20
+
21
+ * The `lang` attribute of the `<html>` tag now respects localization.
22
+ * Fixes the focus styling on AposTable headers.
23
+ * Proper errors when widgets are badly configured in expanded mode.
24
+ * More reliable Media Manager infinite scroll pagination.
25
+ * Fixes margin collapse in nested areas by switching to `padding` instead of `margin`
26
+ * Fixes Edit in Media Manager when the image is not in the currently loaded images. This may happen when the the Media Manager is in a relationship mode.
27
+
28
+ ## 4.13.0 (2025-02-19)
29
+
30
+ ### Adds
31
+
32
+ * Supports progress notification type, can be used when no job are involved. Manage progress state into the new `processes` entity.
33
+ * Moves global notification logic into Pinia store as well as job polling that updates processes.
34
+
35
+ ### Fixes
36
+
37
+ * Field inputs inside an array modal can now be focused/tabbed via keyboard
38
+ * Fixes admin bar overlapping widget area add menu.
39
+ * Fixed the checkered background for gauging color transparency.
40
+ * Fixes `group.operations` (batch configuration) merging between modules in the same way that `group.fields` are merged.
41
+ * The i18n manager detects the current locale correctly in some edge cases, like when the locale is changed per document (Editor Modal) and the localization manager is opened from a relationship manager via a document context menu.
42
+
43
+ ### Adds
44
+
45
+ * Add support for batch localization of pieces and pages.
46
+ * Adds type for each file uploaded by big-upload. Moves big-upload-client to `apos/ui` folder and makes it esm.
47
+ * When present, projections for reverse relationships now automatically include the special id and field storage properties for the relationship in question, allowing the related documents to be successfully returned.
48
+ * Introduce `AposModalReport` component for displaying table reports. It's accessible via `apos.report(content, options)` method and it's now used in the `@apostrophecms/i18n` module for detailed reporting after a batch localization operation.
49
+
50
+ ### Changes
51
+
52
+ * The array editor's `isModified` method is now a computed property for consistency.
53
+ * The `modal` configuration property for batch operations without a group is now accepted and works as expected in the same way as for grouped operations.
54
+ * Explicitly enable document versions for `@apostrophecms/file-tag`, `@apostrophecms/file`, `@apostrophecms/image-tag` and `@apostrophecms/image` piece types.
55
+
56
+ ### Adds
57
+
58
+ * If `error.cause` is prevent, log the property.
59
+
3
60
  ## 4.12.0 (2025-01-27)
4
61
 
5
62
  ### Fixes
package/lib/moog.js CHANGED
@@ -232,6 +232,10 @@ module.exports = function(options) {
232
232
  if (properties.group) {
233
233
  const groups = klona(that[`${cascade}Groups`]);
234
234
  for (const value of Object.values(properties.group)) {
235
+ // Handle `operations` alias of `fields`. Only one of them should be used.
236
+ if (Array.isArray(value.operations)) {
237
+ value.fields = value.operations;
238
+ }
235
239
  for (const field of value.fields || []) {
236
240
  // Remove fields from existing groups if they're added to a new
237
241
  // group.
@@ -252,6 +256,10 @@ module.exports = function(options) {
252
256
  value.fields = groups[key].fields.concat(value.fields);
253
257
  value.label = value.label || groups[key].label;
254
258
  }
259
+ // Copy back `fields` to `operations` (alias).
260
+ if (Array.isArray(value.operations)) {
261
+ value.operations = value.fields;
262
+ }
255
263
  }
256
264
 
257
265
  that[`${cascade}Groups`] = {
@@ -169,7 +169,13 @@ export default {
169
169
  }
170
170
 
171
171
  for (const item of Object.keys(config.widgets)) {
172
- group.widgets.push(apos.modules[`${item}-widget`]);
172
+ const widgetName = `${item}-widget`;
173
+ const widgetModule = apos.modules[widgetName];
174
+ if (!widgetModule) {
175
+ console.error(`${widgetName} is not available in this project, please verify its configuration`);
176
+ } else {
177
+ group.widgets.push(widgetModule);
178
+ }
173
179
  }
174
180
 
175
181
  return group;
@@ -258,6 +264,8 @@ export default {
258
264
  @include type-base;
259
265
 
260
266
  & {
267
+ display: flex;
268
+ flex-direction: column;
261
269
  padding: 0;
262
270
  border: none;
263
271
  border-radius: var(--a-border-radius);
@@ -266,6 +274,7 @@ export default {
266
274
  }
267
275
 
268
276
  .apos-widget__preview {
277
+ margin-bottom: 10px;
269
278
  transition: opacity 250ms ease-in-out;
270
279
 
271
280
  .apos-icon--add {
@@ -6,7 +6,10 @@ const createDOMPurify = require('dompurify');
6
6
  const { JSDOM } = require('jsdom');
7
7
 
8
8
  module.exports = {
9
- options: { alias: 'attachment' },
9
+ options: {
10
+ alias: 'attachment',
11
+ label: 'apostrophe:attachment'
12
+ },
10
13
  cascades: [ 'imageSizes' ],
11
14
  imageSizes: {
12
15
  add: {
@@ -1164,6 +1167,7 @@ module.exports = {
1164
1167
  action: self.action,
1165
1168
  fileGroups: self.fileGroups,
1166
1169
  name: self.name,
1170
+ label: self.options.label,
1167
1171
  // for bc
1168
1172
  uploadsUrl: self.uploadfs.getUrl(),
1169
1173
  croppable: self.croppable,
@@ -32,7 +32,7 @@
32
32
  class="apos-color__active-color"
33
33
  :style="{ background: activeColor }"
34
34
  />
35
- <Checkboard />
35
+ <AposColorCheckerboard />
36
36
  </div>
37
37
  </div>
38
38
  <div v-if="!disableFields" class="apos-color__field">
@@ -97,7 +97,7 @@
97
97
  class="apos-color__presets-color"
98
98
  @click="handlePreset(c)"
99
99
  >
100
- <Checkboard />
100
+ <AposColorCheckerboard />
101
101
  </div>
102
102
  </template>
103
103
  </div>
@@ -110,7 +110,6 @@ import editableInput from '../lib/AposColorEditableInput.vue';
110
110
  import saturation from '../lib/AposColorSaturation.vue';
111
111
  import hue from '../lib/AposColorHue.vue';
112
112
  import alpha from '../lib/AposColorAlpha.vue';
113
- import checkboard from '../lib/AposColorCheckerboard.vue';
114
113
 
115
114
  const defaultOptions = { ...apos.modules['@apostrophecms/color-field'].defaultOptions };
116
115
 
@@ -120,8 +119,7 @@ export default {
120
119
  Saturation: saturation,
121
120
  Hue: hue,
122
121
  Alpha: alpha,
123
- EditableContent: editableInput,
124
- Checkboard: checkboard
122
+ EditableContent: editableInput
125
123
  },
126
124
  mixins: [ colorMixin ],
127
125
  props: {
@@ -296,10 +294,6 @@ export default {
296
294
  box-shadow: inset 0 0 0 1px rgb(0 0 0 / 15%), inset 0 0 4px rgb(0 0 0 / 25%);
297
295
  }
298
296
 
299
- .apos-color__color-wrap .apos-color__checkerboard {
300
- background-size: auto;
301
- }
302
-
303
297
  .apos-color__field {
304
298
  display: flex;
305
299
  padding-top: 4px;
@@ -353,7 +347,7 @@ export default {
353
347
  box-shadow: inset 0 0 0 1px rgb(0 0 0 / 15%);
354
348
  }
355
349
 
356
- .apos-color__presets-color .apos-color__checkerboard {
350
+ .apos-color__presets-color {
357
351
  box-shadow: inset 0 0 0 1px rgb(0 0 0 / 15%);
358
352
  border-radius: 3px;
359
353
  }
@@ -1,13 +1,13 @@
1
1
  <template>
2
2
  <div class="apos-color__alpha">
3
3
  <div class="apos-color__alpha-checkboard-wrap">
4
- <Checkboard />
4
+ <AposColorCheckerboard />
5
5
  </div>
6
6
  <div class="apos-color__alpha-gradient" :style="{ background: gradientColor }" />
7
7
  <div
8
8
  ref="container"
9
9
  class="apos-color__alpha-container"
10
- @mousedown="handleMouseDown"
10
+ @mousedown.prevent="handleMouseDown"
11
11
  @touchmove="handleChange"
12
12
  @touchstart="handleChange"
13
13
  >
@@ -19,13 +19,8 @@
19
19
  </template>
20
20
 
21
21
  <script>
22
- import checkboard from './AposColorCheckerboard.vue';
23
-
24
22
  export default {
25
23
  name: 'AposColorAlpha',
26
- components: {
27
- Checkboard: checkboard
28
- },
29
24
  props: {
30
25
  value: {
31
26
  type: Object,
@@ -7,7 +7,7 @@
7
7
  :aria-valuenow="colors.hsl.h"
8
8
  aria-valuemin="0"
9
9
  aria-valuemax="360"
10
- @mousedown="handleMouseDown"
10
+ @mousedown.prevent="handleMouseDown"
11
11
  @touchmove="handleChange"
12
12
  @touchstart="handleChange"
13
13
  >
@@ -3,7 +3,7 @@
3
3
  ref="container"
4
4
  class="apos-color__saturation"
5
5
  :style="{ background: bgColor }"
6
- @mousedown="handleMouseDown"
6
+ @mousedown.prevent="handleMouseDown"
7
7
  @touchmove="handleChange"
8
8
  @touchstart="handleChange"
9
9
  >
@@ -1751,7 +1751,9 @@ module.exports = {
1751
1751
  const add = [];
1752
1752
  const remove = [];
1753
1753
 
1754
- // Add type in projection by default
1754
+ // Add fundamentals by default to allow Apostrophe's core
1755
+ // operations to find what they expect (determining document type,
1756
+ // distinguishing documents from widgets)
1755
1757
  const hasExclusion = Object.values(projection).some(value => !value);
1756
1758
  if (!_.isEmpty(projection) && !hasExclusion) {
1757
1759
  add.push('type');
@@ -18,6 +18,7 @@ module.exports = {
18
18
  insertViaUpload: true,
19
19
  slugPrefix: 'file-',
20
20
  autopublish: true,
21
+ versions: true,
21
22
  editRole: 'editor',
22
23
  publishRole: 'editor',
23
24
  showPermissions: true,
@@ -81,7 +82,12 @@ module.exports = {
81
82
  }
82
83
  },
83
84
  filters: {
84
- remove: [ 'visibility' ]
85
+ remove: [ 'visibility' ],
86
+ add: {
87
+ _tags: {
88
+ label: 'apostrophe:tags'
89
+ }
90
+ }
85
91
  },
86
92
  methods(self) {
87
93
  return {
@@ -5,6 +5,7 @@ module.exports = {
5
5
  pluralLabel: 'apostrophe:fileTags',
6
6
  quickCreate: false,
7
7
  autopublish: true,
8
+ versions: true,
8
9
  editRole: 'editor',
9
10
  publishRole: 'editor',
10
11
  shortcut: 'G,Shift+F',
@@ -72,34 +72,37 @@ module.exports = (self) => ({
72
72
  await self.bigUploadCleanup();
73
73
  try {
74
74
  const id = self.apos.util.generateId();
75
- files = Object.fromEntries(Object.entries(files).map(([ param, info ]) => {
76
- if ((typeof param) !== 'string') {
77
- throw invalid('param');
78
- }
79
- if (((typeof info) !== 'object') || (info == null)) {
80
- throw invalid('info');
81
- }
82
- if ((typeof info.name) !== 'string') {
83
- throw invalid('name');
84
- }
85
- if (!info.name.length) {
86
- throw invalid('name empty');
87
- }
88
- if ((typeof info.size) !== 'number') {
89
- throw invalid('size');
90
- }
91
- if ((typeof info.chunks) !== 'number') {
92
- throw invalid('chunks');
93
- }
94
- return [ param, {
95
- name: info.name,
96
- size: info.size,
97
- chunks: info.chunks
98
- } ];
99
- }));
75
+ const formattedFiles = Object.fromEntries(
76
+ Object.entries(files).map(([ param, info ]) => {
77
+ if ((typeof param) !== 'string') {
78
+ throw invalid('param');
79
+ }
80
+ if (((typeof info) !== 'object') || (info == null)) {
81
+ throw invalid('info');
82
+ }
83
+ if ((typeof info.name) !== 'string') {
84
+ throw invalid('name');
85
+ }
86
+ if (!info.name.length) {
87
+ throw invalid('name empty');
88
+ }
89
+ if ((typeof info.size) !== 'number') {
90
+ throw invalid('size');
91
+ }
92
+ if ((typeof info.chunks) !== 'number') {
93
+ throw invalid('chunks');
94
+ }
95
+ return [ param, {
96
+ name: info.name,
97
+ size: info.size,
98
+ type: info.type,
99
+ chunks: info.chunks
100
+ } ];
101
+ })
102
+ );
100
103
  await self.bigUploads.insert({
101
104
  _id: id,
102
- files,
105
+ files: formattedFiles,
103
106
  start: Date.now()
104
107
  });
105
108
  return req.res.send({
@@ -162,14 +165,10 @@ module.exports = (self) => ({
162
165
  let n = 0;
163
166
  req.files = {};
164
167
  for (const [ param, {
165
- name, chunks
168
+ name, type, chunks
166
169
  } ] of Object.entries(bigUpload.files)) {
167
- let ext = require('path').extname(name);
168
- if (ext) {
169
- ext = ext.substring(1);
170
- } else {
171
- ext = 'tmp';
172
- }
170
+ const extname = require('path').extname(name);
171
+ const ext = extname ? extname.substring(1) : 'tmp';
173
172
  const tmp = `${ufs.getTempPath()}/${id}-${n}.${ext}`;
174
173
  const out = await open(tmp, 'w');
175
174
  for (let i = 0; (i < chunks); i++) {
@@ -191,7 +190,8 @@ module.exports = (self) => ({
191
190
  n++;
192
191
  req.files[param] = {
193
192
  name,
194
- path: tmp
193
+ path: tmp,
194
+ type
195
195
  };
196
196
  }
197
197
  return next();
@@ -35,11 +35,10 @@ const defaultChunkSize = 1024 * 1024 * 4;
35
35
  // may be specified otherwise the standard Apostrophe `apos.http` object
36
36
  // and the browser's `FormData` are used.
37
37
 
38
- module.exports = async (url, options) => {
38
+ export default async (url, options) => {
39
39
  const chunkSize = options.chunkSize || defaultChunkSize;
40
40
  const http = options.http || window.apos?.http;
41
- const progress = options.progress || (n => {});
42
- const files = options.files || [];
41
+ const files = options.files || {};
43
42
  const info = {};
44
43
  let totalBytes = 0;
45
44
  let sentBytes = 0;
@@ -48,6 +47,7 @@ module.exports = async (url, options) => {
48
47
  info[param] = {
49
48
  name: file.name,
50
49
  size: file.size,
50
+ type: file.type,
51
51
  chunks: Math.ceil(file.size / chunkSize)
52
52
  };
53
53
  }
@@ -81,7 +81,9 @@ module.exports = async (url, options) => {
81
81
  body: formData
82
82
  });
83
83
  sentBytes += thisChunkSize;
84
- progress(sentBytes / totalBytes);
84
+ if (typeof options.progress === 'function') {
85
+ progressInterface(options.progress, sentBytes, totalBytes);
86
+ }
85
87
  chunk++;
86
88
  }
87
89
  n++;
@@ -98,3 +100,15 @@ module.exports = async (url, options) => {
98
100
  });
99
101
  return result;
100
102
  };
103
+
104
+ function progressInterface(fn, sent, total) {
105
+ if (typeof fn !== 'function') {
106
+ return;
107
+ }
108
+ if (fn.length === 1) {
109
+ fn(sent / total);
110
+ return;
111
+ }
112
+
113
+ fn(sent, total);
114
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "description": "NOTE: needed for testing in test/utils.js, for js files to be treated as ESM",
3
+ "type": "module"
4
+ }
@@ -33,19 +33,20 @@
33
33
  "archivingWillDeleteDraftChildren": "Unveröffentlichte Unterseiten werden unwiderruflich gelöscht.",
34
34
  "archivingWillLoseDraftChanges": "Unveröffentlichte Änderungen am {{ type }} werden unwiderruflich gelöscht.",
35
35
  "archivingWillUnpublish": "{{ type }} wird dadurch auch nicht mehr veröffentlicht sein.",
36
- "areaExpandedMenuClipboard": "Zwischenablage",
37
36
  "areYouSure": "Bist du sicher?",
37
+ "areaExpandedMenuClipboard": "Zwischenablage",
38
38
  "arrayCancelDescription": "Willst du die Änderungen an dieser Liste verwerfen?",
39
39
  "aspectRatio": "Bildseitenverhältnis",
40
40
  "aspectRatioFree": "Frei",
41
41
  "aspectRatioWarning": "Das Bildseitenverhältnis kann für diesen Block nicht geändert werden.",
42
+ "assetBuildCacheCleared": "Build-Cache geleert.",
42
43
  "assetBuildWatchStarted": "Warte auf UI-Änderungen...",
43
44
  "assetTypeBuildComplete": "👍 {{ label }} ist abgeschlossen!",
44
45
  "assetTypeBuilding": "🧑‍💻 {{ label }} wird erstellt...",
45
46
  "assetWebpackBundlesWarning": "⚠️ Die Webpack-Konfiguration des Moduls {{ module }} ist fehlerhaft. Jedes Bundle kann nur die Eigenschaft 'templates' enthalten, welches ein String-Array sein muss.",
46
- "assetBuildCacheCleared": "Build-Cache geleert.",
47
47
  "assetWebpackConfigWarning": "⚠️ Die Webpack-Konfiguration des Moduls {{ module }} ist fehlerhaft. Es muss ein Objekt sein und sollte nur die folgenden Eigenschaften enthalten: {{ properties }}.",
48
48
  "at": "um",
49
+ "attachment": "Anhang",
49
50
  "automaticTranslationCheckbox": "Textinhalte übersetzen",
50
51
  "automaticTranslationErrMsg": "Ein Fehler ist aufgetreten beim Abrufen der verfügbaren Sprachen zur Übersetzung. Die Übersetzung wird übersprungen.",
51
52
  "automaticTranslationErrorNoProvider": "Übersetzungsanbieter nicht gefunden. Seite \"{{ title }}\" wurde nicht übersetzt.",
@@ -58,15 +59,17 @@
58
59
  "back": "Zurück",
59
60
  "backToHome": "Zurück zum Start",
60
61
  "basics": "Basics",
61
- "batchArchiveProgress": "Archivierung {{ type }}...",
62
62
  "batchArchiveCompleted": "{{ count }} {{ type }} archiviert.",
63
- "batchPublishProgress": "Veröffentlichung {{ type }}...",
63
+ "batchArchiveProgress": "Archivierung {{ type }}...",
64
64
  "batchPublishCompleted": "{{ count }} {{ type }} veröffentlicht.",
65
- "batchRestoreProgress": "Wiederherstellung {{ type }}...",
65
+ "batchPublishProgress": "Veröffentlichung {{ type }}...",
66
66
  "batchRestoreCompleted": "{{ count }} {{ type }} wiederhergestellt.",
67
+ "batchRestoreProgress": "Wiederherstellung {{ type }}...",
68
+ "breakpointPreviewClear": "Klarer Haltepunkt",
67
69
  "breakpointPreviewDesktop": "Desktop",
68
70
  "breakpointPreviewExit": "Beenden",
69
71
  "breakpointPreviewMobile": "Mobil",
72
+ "breakpointPreviewSelect": "Wählen Sie den Haltepunkt",
70
73
  "breakpointPreviewTablet": "Tablet",
71
74
  "browseDocType": "{{ type }} durchsuchen",
72
75
  "cancel": "Abbrechen",
@@ -131,6 +134,7 @@
131
134
  "deleteTable": "Tabelle löschen",
132
135
  "description": "Beschreibung",
133
136
  "deselectAll": "Alle abwählen",
137
+ "details": "Details",
134
138
  "disabled": "Deaktiviert",
135
139
  "discardChanges": "Änderungen verwerfen",
136
140
  "discardChangesPrompt": "Willst du die Änderungen verwerfen?",
@@ -151,6 +155,7 @@
151
155
  "doesNotExistYet": "Existiert noch nicht",
152
156
  "doesNotExistYetDescription": "Dieses Dokument existiert noch nicht als {{ mode }} in {{ locale }}.",
153
157
  "download": "Herunterladen",
158
+ "downloadAs": "Herunterladen as",
154
159
  "draft": "Entwurf",
155
160
  "draftDeleted": "Entwurf gelöscht",
156
161
  "draftDiscarded": "Entwurf verworfen",
@@ -158,8 +163,8 @@
158
163
  "draftSavedNoPreview": "Entwurf gespeichert, aber es konnte keine Vorschau angezeigt werden.",
159
164
  "dropMedia": "Medien hierher ziehen",
160
165
  "duplicate": "Duplizieren",
161
- "duplicateOf": "Duplikat von",
162
166
  "duplicateError": "Duplikat",
167
+ "duplicateOf": "Duplikat von",
163
168
  "edit": "Bearbeiten",
164
169
  "editImageAdjustments": "Bildanpassungen",
165
170
  "editImageRelationshipTitle": "Bild anpassen",
@@ -231,10 +236,10 @@
231
236
  "i18nCurrentlySelectedLocale": "Aktuell ausgewählte Sprache",
232
237
  "i18nDefaultLocale": "Standardsprache",
233
238
  "image": "Bild",
234
- "imageOnReplaceAutocropMessage": "Das ersetzte Bild wurde für \"{{ title }}\" automatisch zugeschnitten.",
235
- "imageOnReplaceAutocropError": "Ein Fehler ist aufgetreten beim automatischen Zuschnitt des ersetzten Bildes für {{ title }}",
236
239
  "imageDescription": "Fügen Sie ein Bild ein",
237
240
  "imageFile": "Bilddatei",
241
+ "imageOnReplaceAutocropError": "Ein Fehler ist aufgetreten beim automatischen Zuschnitt des ersetzten Bildes für {{ title }}",
242
+ "imageOnReplaceAutocropMessage": "Das ersetzte Bild wurde für \"{{ title }}\" automatisch zugeschnitten.",
238
243
  "imagePlaceholder": "Bild-Platzhalter",
239
244
  "imageTag": "Bild-Tag",
240
245
  "imageTags": "Bild-Tags",
@@ -266,7 +271,18 @@
266
271
  "localizeNewRelated": "Übersetze alle neuen zugehörige Dokumente",
267
272
  "localizeNotYetLocalized": "Noch nicht lokalisiert",
268
273
  "localized": "{{ type }} {{ title }} auf {{ locale }} übersetzt",
274
+ "localizedBatch": "Verarbeitet {{ count }} {{ type }}",
275
+ "localizingBatch": "Lokalisierung {{ type }} ...",
269
276
  "localizingBusy": "Übersetze Inhalt",
277
+ "localizingNotificationDanger": "{{ count }} Dokument kann nicht lokalisiert werden",
278
+ "localizingNotificationDanger_plural": "{{ count }} Dokumente können nicht lokalisiert werden",
279
+ "localizingNotificationSuccess": "{{ count }} Dokument erfolgreich lokalisiert",
280
+ "localizingNotificationSuccess_plural": "{{ count }} Dokumente erfolgreich lokalisiert",
281
+ "localizingNotificationWarning": "{{ count }} Dokument erfolgreich lokalisiert, {{ SkipCount }} übersprungen",
282
+ "localizingNotificationWarning_plural": "{{ count }} Dokumente erfolgreich lokalisiert, {{ SkipCount }} übersprungen",
283
+ "localizingReportDesc": "Einige Dokumente konnten nicht lokalisiert werden. ",
284
+ "localizingReportHeading": "{{ count }} Dokument konnte nicht lokalisiert werden",
285
+ "localizingReportHeading_plural": "{{ count }} Dokumente konnten nicht lokalisiert werden",
270
286
  "logOut": "Abmelden",
271
287
  "logOutNotLoggedIn": "Du bist nicht angemeldet.",
272
288
  "login": "Anmelden",
@@ -381,17 +397,15 @@
381
397
  "piecePermissionsPieceTypeList": "Piece-Typen:",
382
398
  "preview": "Vorschau",
383
399
  "previewTooltip": "Vorschau-Modus",
384
- "updateTooltip": "Updates veröffentlichen",
385
400
  "previousPage": "Vorherige Seite",
386
401
  "provideButtonLabel": "Knopftitel angeben",
387
402
  "public": "Öffentlich",
388
403
  "publish": "Veröffentlichen",
389
404
  "publishBeforeUsingTooltip": "Veröffentliche diese Seite, bevor du sie in einer Beziehung benutzt.",
390
- "publishType": "{{ type }} veröffentlichen",
405
+ "publishType": "{{  type }} veröffentlichen",
391
406
  "published": "Veröffentlicht",
392
407
  "publishingBatchConfirmation": "Willst du {{ count }} {{ type }} wirklich veröffentlichen?",
393
408
  "publishingBatchConfirmationButton": "Ja, Inhalt veröffentlichen.",
394
- "required": "erforderlich",
395
409
  "rawCssAndJs": "CSS und JavaScript",
396
410
  "rawHtml": "HTML",
397
411
  "rawHtmlCode": "HTML (Code)",
@@ -406,6 +420,7 @@
406
420
  "relatedDocTypesToLocalize": "Zu übersetzende verwandte Dokumenttypen",
407
421
  "relatedDocsDefinition": "Verwandte Dokumente sind Dokumente, auf die in diesem Dokument verwiesen wird. Dazu gehören in der Regel Bilder, durch Beziehungen definierte Inhalte usw.",
408
422
  "relatedDocsOnly": "Nur verwandte Dokumente",
423
+ "relationship": "Beziehung",
409
424
  "relationshipSuggestionHelp": "Tippen Sie, um alle {{ type }} zu durchsuchen...",
410
425
  "relationshipSuggestionLabel": "Vorschläge",
411
426
  "relationshipSuggestionNoResults": "Kann nicht finden, wonach Sie suchen?",
@@ -416,8 +431,9 @@
416
431
  "removeLink": "Link entfernen",
417
432
  "removeRichTextAnchor": "Rich-Text-Anker entfernen",
418
433
  "replace": "Ersetzen",
419
- "replaceHeadingPrompt": "Dokument ersetzen?",
420
434
  "replaceDescPrompt": "Diese Operation wird die Inhalte dieses Dokuments ersetzen. Sind Sie sicher?",
435
+ "replaceHeadingPrompt": "Dokument ersetzen?",
436
+ "required": "erforderlich",
421
437
  "resolveErrorsBeforeSaving": "Behebe zuerst die Fehler, bevor du speicherst.",
422
438
  "resolveErrorsFirst": "Behebe zuerst die Fehler.",
423
439
  "restore": "Wiederherstellen",
@@ -429,8 +445,8 @@
429
445
  "restoreTypeAffirmativeLabel": "Ja, {{ type }} wiederherstellen",
430
446
  "restoredPrevious": "Vorherige veröffentlichte Version wiederhergestellt.",
431
447
  "resumeEditing": "Bearbeitung fortsetzen",
432
- "retryingSaveDocument": "Versuche Dokument zu speichern...",
433
448
  "retry": "Erneut versuchen",
449
+ "retryingSaveDocument": "Versuche Dokument zu speichern...",
434
450
  "returnToPage": "Zu {{ label }} zurückkehren",
435
451
  "richText": "Rich-Text",
436
452
  "richTextAlignCenter": "Zentrieren",
@@ -454,8 +470,8 @@
454
470
  "richTextMarkApplyStyles": "Stil anwenden",
455
471
  "richTextMarkMultipleStyles": "Mehrere stile...",
456
472
  "richTextMarkStyles": "Inline Stile",
457
- "richTextNodeStyles": "Block Stile",
458
473
  "richTextNodeMultipleStyles": "Mehrere blocks...",
474
+ "richTextNodeStyles": "Block Stile",
459
475
  "richTextOrderedList": "Nummerierte Liste",
460
476
  "richTextParagraph": "Paragraph",
461
477
  "richTextPlaceholder": "Beginne dein Text hier...",
@@ -465,6 +481,7 @@
465
481
  "richTextStyleConfigWarning": "Falsche Konfiguration des Text-Stiles: {{ label }}, {{ tag }}",
466
482
  "richTextUnderline": "Unterstrichen",
467
483
  "richTextUndo": "Rückgängig",
484
+ "richTextUploadCsvTable": "Laden Sie eine CSV-Datei hoch, um eine Tabelle zu erstellen.",
468
485
  "role": "Rolle",
469
486
  "safeModeActive": "Sicherer Modus aktiv, HTML-Code wird nicht gerendert.",
470
487
  "save": "Speichern",
@@ -523,14 +540,15 @@
523
540
  "switchLocalesAndLocalizePage": "Sprache ändern zu {{ label }}?",
524
541
  "table": "Tabelle",
525
542
  "tableDescription": "Fügen Sie tabellarische Inhalte zu Ihrer Seite hinzu",
543
+ "tableImport": "Tabelle importieren",
526
544
  "tagAddTag": "Tag hinzufügen",
527
- "tagSearchApplyTags": "Tags anwenden",
528
- "tagSearchPlaceholder": "Tags...",
529
- "tagCreateTag": "Tag \"{{ tag }}\" erstellen",
530
545
  "tagCreateNewTag": "Neuen Tag erstellen",
546
+ "tagCreateTag": "Tag \"{{ tag }}\" erstellen",
531
547
  "tagNewTag": "Neuer Tag",
532
548
  "tagNoTagsFoundCreateOne": "Erstellen {{ tag }}?",
533
549
  "tagNoTagsFoundPerhaps": "Wir konnten keine passenden Tags finden. Vielleicht",
550
+ "tagSearchApplyTags": "Tags anwenden",
551
+ "tagSearchPlaceholder": "Tags...",
534
552
  "tagYourImages": "Weise deinen Bildern Tags zu, um die Suche und das Filtern im Medienmanager zu erleichtern.",
535
553
  "tags": "Tags",
536
554
  "takeActionAndCreateNew": "{{ saveLabel }} und erstelle Neues",
@@ -538,7 +556,8 @@
538
556
  "takeControlFromOther": "{{ who }} bearbeitet dieses Dokument. Willst du die Kontrolle übernehmen?",
539
557
  "takeControlFromSelf": "Du bearbeitest dieses Dokument in einer anderen Registerkarte oder einem anderen Fenster. Möchtest du die Kontrolle in dieser Registerkarte übernehmen?",
540
558
  "thereAreActiveChanges": "Es gibt Änderungen an diesem Dokument.",
541
- "thereWasAnIssueLocalizing": "Es ist ein Fehler beim Übersetzen des Inhalts aufgetreten:",
559
+ "theseDocuments": "Diese Dokumente",
560
+ "theseDocumentsAndRelated": "Diese Dokumente und verwandten Dokumente",
542
561
  "thisDocument": "Dieses Dokument",
543
562
  "thisDocumentAndRelated": "Dieses und alle zugehörigen Dokumente",
544
563
  "title": "Titel",
@@ -551,9 +570,9 @@
551
570
  "treeError": "Beim Aktualisieren des Seitenbaums ist ein Fehler aufgetreten.",
552
571
  "type": "Typ",
553
572
  "typeWithCount": "{{ type }} ({{ count }})",
554
- "unableToSwitchModes": "Modus kann nicht geändert werden.",
555
573
  "uiLanguageLabel": "UI-Sprache",
556
574
  "uiLanguageWebsite": "Gleich wie Website",
575
+ "unableToSwitchModes": "Modus kann nicht geändert werden.",
557
576
  "undo": "Rückgängig",
558
577
  "undoFailed": "Änderung konnte nicht Rückgängig gemacht werden.",
559
578
  "undoPublish": "Veröffentlichung rückgängig machen",
@@ -571,6 +590,7 @@
571
590
  "updateAndReturn": "Änderungen {{ saveLabel }} und zur {{ typeLabel }} Auflistung zurückkehren.",
572
591
  "updateSingleton": "{{ saveLabel }} {{ typeLabel }}.",
573
592
  "updateTitle": "Titel aktualisieren",
593
+ "updateTooltip": "Updates veröffentlichen",
574
594
  "updated": "Änderungen veröffentlicht",
575
595
  "uploadError": "Fehler beim Hochladen",
576
596
  "uploadForbidden": "Du hast keine Berechtigung, Dateien hochzuladen.",
@@ -593,4 +613,4 @@
593
613
  "yes": "Ja",
594
614
  "yesLocalizeAndSwitchLocales": "Ja, diese Seite übersetzen und zu der Sprache wechseln.",
595
615
  "youTookControl": "Du hast die Kontrolle über dieses Dokument in einer anderen Registerkarte oder einem anderen Fenster übernommen. Ein Dokument kann immer nur an einer Stelle bearbeitet werden."
596
- }
616
+ }