mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 18:36:30 +01:00 
			
		
		
		
	Merge branch 'develop' into siriusxt_patch
This commit is contained in:
		| @@ -18,6 +18,8 @@ See [screenshots](https://triliumnext.github.io/Docs/Wiki/screenshot-tour) for q | |||||||
|  |  | ||||||
| There are no special migration steps to migrate from a zadam/Trilium instance to a TriliumNext/Notes instance. Just upgrade your Trilium instance to the latest version and [install TriliumNext/Notes as usual](#-installation)  | There are no special migration steps to migrate from a zadam/Trilium instance to a TriliumNext/Notes instance. Just upgrade your Trilium instance to the latest version and [install TriliumNext/Notes as usual](#-installation)  | ||||||
|  |  | ||||||
|  | Versions up to and including [v0.90.4](https://github.com/TriliumNext/Notes/releases/tag/v0.90.4) are compatible with the latest zadam/trilium version of [v0.63.7](https://github.com/zadam/trilium/releases/tag/v0.63.7). Any later versions of TriliumNext have their sync versions incremented. | ||||||
|  |  | ||||||
| ## 💬 Discuss with us | ## 💬 Discuss with us | ||||||
|  |  | ||||||
| Feel free to join our official conversations. We would love to hear what features, suggestions, or issues you may have! | Feel free to join our official conversations. We would love to hear what features, suggestions, or issues you may have! | ||||||
|   | |||||||
							
								
								
									
										49
									
								
								libraries/ckeditor/ckeditor.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								libraries/ckeditor/ckeditor.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | |||||||
|  | /** | ||||||
|  |  * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. | ||||||
|  |  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license | ||||||
|  |  */ | ||||||
|  | import { DecoupledEditor as DecoupledEditorBase } from '@ckeditor/ckeditor5-editor-decoupled'; | ||||||
|  | import { Essentials } from '@ckeditor/ckeditor5-essentials'; | ||||||
|  | import { Alignment } from '@ckeditor/ckeditor5-alignment'; | ||||||
|  | import { FontSize, FontFamily, FontColor, FontBackgroundColor } from '@ckeditor/ckeditor5-font'; | ||||||
|  | import { CKFinderUploadAdapter } from '@ckeditor/ckeditor5-adapter-ckfinder'; | ||||||
|  | import { Autoformat } from '@ckeditor/ckeditor5-autoformat'; | ||||||
|  | import { Bold, Italic, Strikethrough, Underline } from '@ckeditor/ckeditor5-basic-styles'; | ||||||
|  | import { BlockQuote } from '@ckeditor/ckeditor5-block-quote'; | ||||||
|  | import { CKBox } from '@ckeditor/ckeditor5-ckbox'; | ||||||
|  | import { CKFinder } from '@ckeditor/ckeditor5-ckfinder'; | ||||||
|  | import { EasyImage } from '@ckeditor/ckeditor5-easy-image'; | ||||||
|  | import { Heading } from '@ckeditor/ckeditor5-heading'; | ||||||
|  | import { Image, ImageCaption, ImageResize, ImageStyle, ImageToolbar, ImageUpload, PictureEditing } from '@ckeditor/ckeditor5-image'; | ||||||
|  | import { Indent, IndentBlock } from '@ckeditor/ckeditor5-indent'; | ||||||
|  | import { Link } from '@ckeditor/ckeditor5-link'; | ||||||
|  | import { List, ListProperties } from '@ckeditor/ckeditor5-list'; | ||||||
|  | import { MediaEmbed } from '@ckeditor/ckeditor5-media-embed'; | ||||||
|  | import { Paragraph } from '@ckeditor/ckeditor5-paragraph'; | ||||||
|  | import { PasteFromOffice } from '@ckeditor/ckeditor5-paste-from-office'; | ||||||
|  | import { Table, TableToolbar } from '@ckeditor/ckeditor5-table'; | ||||||
|  | import { TextTransformation } from '@ckeditor/ckeditor5-typing'; | ||||||
|  | import { CloudServices } from '@ckeditor/ckeditor5-cloud-services'; | ||||||
|  | export default class DecoupledEditor extends DecoupledEditorBase { | ||||||
|  |     static builtinPlugins: (typeof TextTransformation | typeof Essentials | typeof Alignment | typeof FontBackgroundColor | typeof FontColor | typeof FontFamily | typeof FontSize | typeof CKFinderUploadAdapter | typeof Paragraph | typeof Heading | typeof Autoformat | typeof Bold | typeof Italic | typeof Strikethrough | typeof Underline | typeof BlockQuote | typeof Image | typeof ImageCaption | typeof ImageResize | typeof ImageStyle | typeof ImageToolbar | typeof ImageUpload | typeof CloudServices | typeof CKBox | typeof CKFinder | typeof EasyImage | typeof List | typeof ListProperties | typeof Indent | typeof IndentBlock | typeof Link | typeof MediaEmbed | typeof PasteFromOffice | typeof Table | typeof TableToolbar | typeof PictureEditing)[]; | ||||||
|  |     static defaultConfig: { | ||||||
|  |         toolbar: { | ||||||
|  |             items: string[]; | ||||||
|  |         }; | ||||||
|  |         image: { | ||||||
|  |             resizeUnit: "px"; | ||||||
|  |             toolbar: string[]; | ||||||
|  |         }; | ||||||
|  |         table: { | ||||||
|  |             contentToolbar: string[]; | ||||||
|  |         }; | ||||||
|  |         list: { | ||||||
|  |             properties: { | ||||||
|  |                 styles: boolean; | ||||||
|  |                 startIndex: boolean; | ||||||
|  |                 reversed: boolean; | ||||||
|  |             }; | ||||||
|  |         }; | ||||||
|  |         language: string; | ||||||
|  |     }; | ||||||
|  | } | ||||||
							
								
								
									
										2
									
								
								libraries/ckeditor/ckeditor.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								libraries/ckeditor/ckeditor.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -82,6 +82,7 @@ import MovePaneButton from "../widgets/buttons/move_pane_button.js"; | |||||||
| import UploadAttachmentsDialog from "../widgets/dialogs/upload_attachments.js"; | import UploadAttachmentsDialog from "../widgets/dialogs/upload_attachments.js"; | ||||||
| import CopyImageReferenceButton from "../widgets/floating_buttons/copy_image_reference_button.js"; | import CopyImageReferenceButton from "../widgets/floating_buttons/copy_image_reference_button.js"; | ||||||
| import ScrollPaddingWidget from "../widgets/scroll_padding.js"; | import ScrollPaddingWidget from "../widgets/scroll_padding.js"; | ||||||
|  | import ClassicEditorToolbar from "../widgets/ribbon_widgets/classic_editor_toolbar.js"; | ||||||
|  |  | ||||||
| export default class DesktopLayout { | export default class DesktopLayout { | ||||||
|     constructor(customWidgets) { |     constructor(customWidgets) { | ||||||
| @@ -140,6 +141,7 @@ export default class DesktopLayout { | |||||||
|                                             // the order of the widgets matter. Some of these want to "activate" themselves |                                             // the order of the widgets matter. Some of these want to "activate" themselves | ||||||
|                                             // when visible. When this happens to multiple of them, the first one "wins". |                                             // when visible. When this happens to multiple of them, the first one "wins". | ||||||
|                                             // promoted attributes should always win. |                                             // promoted attributes should always win. | ||||||
|  |                                             .ribbon(new ClassicEditorToolbar()) | ||||||
|                                             .ribbon(new PromotedAttributesWidget()) |                                             .ribbon(new PromotedAttributesWidget()) | ||||||
|                                             .ribbon(new ScriptExecutorWidget()) |                                             .ribbon(new ScriptExecutorWidget()) | ||||||
|                                             .ribbon(new SearchDefinitionWidget()) |                                             .ribbon(new SearchDefinitionWidget()) | ||||||
|   | |||||||
| @@ -23,6 +23,7 @@ import LauncherContainer from "../widgets/containers/launcher_container.js"; | |||||||
| import RootContainer from "../widgets/containers/root_container.js"; | import RootContainer from "../widgets/containers/root_container.js"; | ||||||
| import SharedInfoWidget from "../widgets/shared_info.js"; | import SharedInfoWidget from "../widgets/shared_info.js"; | ||||||
| import PromotedAttributesWidget from "../widgets/ribbon_widgets/promoted_attributes.js"; | import PromotedAttributesWidget from "../widgets/ribbon_widgets/promoted_attributes.js"; | ||||||
|  | import ClassicEditorToolbar from "../widgets/ribbon_widgets/classic_editor_toolbar.js"; | ||||||
|  |  | ||||||
| const MOBILE_CSS = ` | const MOBILE_CSS = ` | ||||||
| <style> | <style> | ||||||
| @@ -167,6 +168,7 @@ export default class MobileLayout { | |||||||
|                             .child(new NoteListWidget()) |                             .child(new NoteListWidget()) | ||||||
|                             .child(new FilePropertiesWidget().css('font-size','smaller')) |                             .child(new FilePropertiesWidget().css('font-size','smaller')) | ||||||
|                     ) |                     ) | ||||||
|  |                     .child(new ClassicEditorToolbar()) | ||||||
|                 ) |                 ) | ||||||
|                 .child(new ProtectedSessionPasswordDialog()) |                 .child(new ProtectedSessionPasswordDialog()) | ||||||
|                 .child(new ConfirmDialog()) |                 .child(new ConfirmDialog()) | ||||||
|   | |||||||
| @@ -527,6 +527,58 @@ function downloadSvg(nameWithoutExtension, svgContent) { | |||||||
|     document.body.removeChild(element); |     document.body.removeChild(element); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Compares two semantic version strings. | ||||||
|  |  * Returns: | ||||||
|  |  *   1  if v1 is greater than v2 | ||||||
|  |  *   0  if v1 is equal to v2 | ||||||
|  |  *   -1 if v1 is less than v2 | ||||||
|  |  *  | ||||||
|  |  * @param {string} v1 First version string | ||||||
|  |  * @param {string} v2 Second version string | ||||||
|  |  * @returns {number} | ||||||
|  |  */ | ||||||
|  | function compareVersions(v1, v2) { | ||||||
|  |  | ||||||
|  |     // Remove 'v' prefix and everything after dash if present | ||||||
|  |     v1 = v1.replace(/^v/, '').split('-')[0]; | ||||||
|  |     v2 = v2.replace(/^v/, '').split('-')[0]; | ||||||
|  |      | ||||||
|  |     const v1parts = v1.split('.').map(Number); | ||||||
|  |     const v2parts = v2.split('.').map(Number); | ||||||
|  |      | ||||||
|  |     // Pad shorter version with zeros | ||||||
|  |     while (v1parts.length < 3) v1parts.push(0); | ||||||
|  |     while (v2parts.length < 3) v2parts.push(0); | ||||||
|  |      | ||||||
|  |     // Compare major version | ||||||
|  |     if (v1parts[0] !== v2parts[0]) { | ||||||
|  |         return v1parts[0] > v2parts[0] ? 1 : -1; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     // Compare minor version | ||||||
|  |     if (v1parts[1] !== v2parts[1]) { | ||||||
|  |         return v1parts[1] > v2parts[1] ? 1 : -1; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     // Compare patch version | ||||||
|  |     if (v1parts[2] !== v2parts[2]) { | ||||||
|  |         return v1parts[2] > v2parts[2] ? 1 : -1; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Compares two semantic version strings and returns `true` if the latest version is greater than the current version. | ||||||
|  |  * @param {string} latestVersion | ||||||
|  |  * @param {string} currentVersion | ||||||
|  |  * @returns {boolean} | ||||||
|  |  */ | ||||||
|  | function isUpdateAvailable(latestVersion, currentVersion) { | ||||||
|  |     return compareVersions(latestVersion, currentVersion) > 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| export default { | export default { | ||||||
|     reloadFrontendApp, |     reloadFrontendApp, | ||||||
|     parseDate, |     parseDate, | ||||||
| @@ -567,5 +619,7 @@ export default { | |||||||
|     areObjectsEqual, |     areObjectsEqual, | ||||||
|     copyHtmlToClipboard, |     copyHtmlToClipboard, | ||||||
|     createImageSrcUrl, |     createImageSrcUrl, | ||||||
|     downloadSvg |     downloadSvg, | ||||||
|  |     compareVersions, | ||||||
|  |     isUpdateAvailable | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -347,8 +347,7 @@ export default class AttributeEditorWidget extends NoteContextAwareWidget { | |||||||
|  |  | ||||||
|         this.$editor.on("click", e => this.handleEditorClick(e)); |         this.$editor.on("click", e => this.handleEditorClick(e)); | ||||||
|  |  | ||||||
|         /** @property {BalloonEditor} */ |         this.textEditor = await CKEditor.BalloonEditor.create(this.$editor[0], editorConfig); | ||||||
|         this.textEditor = await BalloonEditor.create(this.$editor[0], editorConfig); |  | ||||||
|         this.textEditor.model.document.on('change:data', () => this.dataChanged()); |         this.textEditor.model.document.on('change:data', () => this.dataChanged()); | ||||||
|         this.textEditor.editing.view.document.on('enter', (event, data) => { |         this.textEditor.editing.view.document.on('enter', (event, data) => { | ||||||
|             // disable entering new line - see https://github.com/ckeditor/ckeditor5/issues/9422 |             // disable entering new line - see https://github.com/ckeditor/ckeditor5/issues/9422 | ||||||
| @@ -358,9 +357,6 @@ export default class AttributeEditorWidget extends NoteContextAwareWidget { | |||||||
|  |  | ||||||
|         // disable spellcheck for attribute editor |         // disable spellcheck for attribute editor | ||||||
|         this.textEditor.editing.view.change(writer => writer.setAttribute('spellcheck', 'false', this.textEditor.editing.view.document.getRoot())); |         this.textEditor.editing.view.change(writer => writer.setAttribute('spellcheck', 'false', this.textEditor.editing.view.document.getRoot())); | ||||||
|  |  | ||||||
|         //await import(/* webpackIgnore: true */'../../libraries/ckeditor/inspector'); |  | ||||||
|         //CKEditorInspector.attach(this.textEditor); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     dataChanged() { |     dataChanged() { | ||||||
|   | |||||||
| @@ -333,7 +333,8 @@ export default class GlobalMenuWidget extends BasicWidget { | |||||||
|  |  | ||||||
|         const latestVersion = await this.fetchLatestVersion(); |         const latestVersion = await this.fetchLatestVersion(); | ||||||
|         this.updateAvailableWidget.updateVersionStatus(latestVersion); |         this.updateAvailableWidget.updateVersionStatus(latestVersion); | ||||||
|         this.$updateToLatestVersionButton.toggle(latestVersion > glob.triliumVersion); |         // Show "click to download" button in options menu if there's a new version available | ||||||
|  |         this.$updateToLatestVersionButton.toggle(utils.isUpdateAvailable(latestVersion, glob.triliumVersion)); | ||||||
|         this.$updateToLatestVersionButton.find(".version-text").text(`Version ${latestVersion} is available, click to download.`); |         this.$updateToLatestVersionButton.find(".version-text").text(`Version ${latestVersion} is available, click to download.`); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| import { t } from "../../services/i18n.js"; | import { t } from "../../services/i18n.js"; | ||||||
| import BasicWidget from "../basic_widget.js"; | import BasicWidget from "../basic_widget.js"; | ||||||
|  | import utils from "../../services/utils.js"; | ||||||
|  |  | ||||||
| const TPL = ` | const TPL = ` | ||||||
| <div style="display: none;"> | <div style="display: none;"> | ||||||
| @@ -34,6 +35,6 @@ export default class UpdateAvailableWidget extends BasicWidget { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     updateVersionStatus(latestVersion) { |     updateVersionStatus(latestVersion) { | ||||||
|         this.$widget.toggle(latestVersion > glob.triliumVersion); |         this.$widget.toggle(utils.isUpdateAvailable(latestVersion, glob.triliumVersion)); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -216,7 +216,7 @@ export default class RibbonContainer extends NoteContextAwareWidget { | |||||||
|         this.$tabContainer.empty(); |         this.$tabContainer.empty(); | ||||||
|  |  | ||||||
|         for (const ribbonWidget of this.ribbonWidgets) { |         for (const ribbonWidget of this.ribbonWidgets) { | ||||||
|             const ret = ribbonWidget.getTitle(note); |             const ret = await ribbonWidget.getTitle(note); | ||||||
|  |  | ||||||
|             if (!ret.show) { |             if (!ret.show) { | ||||||
|                 continue; |                 continue; | ||||||
| @@ -351,6 +351,16 @@ export default class RibbonContainer extends NoteContextAwareWidget { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Executed as soon as the user presses the "Edit" floating button in a read-only text note. | ||||||
|  |      *  | ||||||
|  |      * <p> | ||||||
|  |      * We need to refresh the ribbon for cases such as the classic editor which relies on the read-only state. | ||||||
|  |      */ | ||||||
|  |     readOnlyTemporarilyDisabledEvent() {         | ||||||
|  |         this.refresh(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     getActiveRibbonWidget() { |     getActiveRibbonWidget() { | ||||||
|         return this.ribbonWidgets.find(ch => ch.componentId === this.lastActiveComponentId) |         return this.ribbonWidgets.find(ch => ch.componentId === this.lastActiveComponentId) | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -0,0 +1,83 @@ | |||||||
|  | import { t } from "../../services/i18n.js"; | ||||||
|  | import options from "../../services/options.js"; | ||||||
|  | import NoteContextAwareWidget from "../note_context_aware_widget.js"; | ||||||
|  |  | ||||||
|  | const TPL = `\ | ||||||
|  | <div class="classic-toolbar-widget"></div> | ||||||
|  |  | ||||||
|  | <style> | ||||||
|  |     .classic-toolbar-widget { | ||||||
|  |         --ck-color-toolbar-background: transparent; | ||||||
|  |         --ck-color-button-default-background: transparent;         | ||||||
|  |         --ck-color-button-default-disabled-background: transparent; | ||||||
|  |         min-height: 39px; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .classic-toolbar-widget .ck.ck-toolbar { | ||||||
|  |         border: none; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .classic-toolbar-widget .ck.ck-button.ck-disabled { | ||||||
|  |         opacity: 0.3; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     body.mobile .classic-toolbar-widget { | ||||||
|  |         position: relative; | ||||||
|  |         overflow-x: auto; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     body.mobile .classic-toolbar-widget .ck.ck-toolbar { | ||||||
|  |         position: absolute; | ||||||
|  |     } | ||||||
|  | </style> | ||||||
|  | `; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Handles the editing toolbar when the CKEditor is in decoupled mode. | ||||||
|  |  *  | ||||||
|  |  * <p> | ||||||
|  |  * This toolbar is only enabled if the user has selected the classic CKEditor. | ||||||
|  |  *  | ||||||
|  |  * <p> | ||||||
|  |  * The ribbon item is active by default for text notes, as long as they are not in read-only mode. | ||||||
|  |  */ | ||||||
|  | export default class ClassicEditorToolbar extends NoteContextAwareWidget { | ||||||
|  |     get name() { | ||||||
|  |         return "classicEditor"; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     get toggleCommand() { | ||||||
|  |         return "toggleRibbonTabClassicEditor"; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     doRender() { | ||||||
|  |         this.$widget = $(TPL); | ||||||
|  |         this.contentSized(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     async getTitle() { | ||||||
|  |         return { | ||||||
|  |             show: await this.#shouldDisplay(), | ||||||
|  |             activate: true, | ||||||
|  |             title: t("classic_editor_toolbar.title"), | ||||||
|  |             icon: "bx bx-edit-alt" | ||||||
|  |         }; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     async #shouldDisplay() { | ||||||
|  |         if (options.get("textNoteEditorType") !== "ckeditor-classic") { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (this.note.type !== "text") { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (await this.noteContext.isReadOnly()) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -35,6 +35,7 @@ import AttachmentErasureTimeoutOptions from "./options/other/attachment_erasure_ | |||||||
| import RibbonOptions from "./options/appearance/ribbon.js"; | import RibbonOptions from "./options/appearance/ribbon.js"; | ||||||
| import LocalizationOptions from "./options/appearance/i18n.js"; | import LocalizationOptions from "./options/appearance/i18n.js"; | ||||||
| import CodeBlockOptions from "./options/appearance/code_block.js"; | import CodeBlockOptions from "./options/appearance/code_block.js"; | ||||||
|  | import EditorOptions from "./options/text_notes/editor.js"; | ||||||
|  |  | ||||||
| const TPL = `<div class="note-detail-content-widget note-detail-printable"> | const TPL = `<div class="note-detail-content-widget note-detail-printable"> | ||||||
|     <style> |     <style> | ||||||
| @@ -68,6 +69,7 @@ const CONTENT_WIDGETS = { | |||||||
|     ], |     ], | ||||||
|     _optionsShortcuts: [ KeyboardShortcutsOptions ], |     _optionsShortcuts: [ KeyboardShortcutsOptions ], | ||||||
|     _optionsTextNotes: [ |     _optionsTextNotes: [ | ||||||
|  |         EditorOptions, | ||||||
|         HeadingStyleOptions, |         HeadingStyleOptions, | ||||||
|         TableOfContentsOptions, |         TableOfContentsOptions, | ||||||
|         HighlightsListOptions, |         HighlightsListOptions, | ||||||
|   | |||||||
| @@ -12,7 +12,6 @@ import appContext from "../../components/app_context.js"; | |||||||
| import dialogService from "../../services/dialog.js"; | import dialogService from "../../services/dialog.js"; | ||||||
| import { initSyntaxHighlighting } from "./ckeditor/syntax_highlight.js"; | import { initSyntaxHighlighting } from "./ckeditor/syntax_highlight.js"; | ||||||
| import options from "../../services/options.js"; | import options from "../../services/options.js"; | ||||||
| import { isSyntaxHighlightEnabled } from "../../services/syntax_highlight.js"; |  | ||||||
|  |  | ||||||
| const ENABLE_INSPECTOR = false; | const ENABLE_INSPECTOR = false; | ||||||
|  |  | ||||||
| @@ -107,6 +106,12 @@ function buildListOfLanguages() { | |||||||
|     ]; |     ]; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * The editor can operate into two distinct modes: | ||||||
|  |  *  | ||||||
|  |  * - Ballon block mode, in which there is a floating toolbar for the selected text, but another floating button for the entire block (i.e. paragraph). | ||||||
|  |  * - Decoupled mode, in which the editing toolbar is actually added on the client side (in {@link ClassicEditorToolbar}), see https://ckeditor.com/docs/ckeditor5/latest/examples/framework/bottom-toolbar-editor.html for an example on how the decoupled editor works. | ||||||
|  |  */ | ||||||
| export default class EditableTextTypeWidget extends AbstractTextTypeWidget { | export default class EditableTextTypeWidget extends AbstractTextTypeWidget { | ||||||
|     static getType() { return "editableText"; } |     static getType() { return "editableText"; } | ||||||
|  |  | ||||||
| @@ -125,6 +130,8 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget { | |||||||
|  |  | ||||||
|     async initEditor() { |     async initEditor() { | ||||||
|         await libraryLoader.requireLibrary(libraryLoader.CKEDITOR); |         await libraryLoader.requireLibrary(libraryLoader.CKEDITOR); | ||||||
|  |         const isClassicEditor = (options.get("textNoteEditorType") === "ckeditor-classic") | ||||||
|  |         const editorClass = (isClassicEditor ? CKEditor.DecoupledEditor : CKEditor.BalloonEditor); | ||||||
|  |  | ||||||
|         const codeBlockLanguages = buildListOfLanguages(); |         const codeBlockLanguages = buildListOfLanguages(); | ||||||
|  |  | ||||||
| @@ -133,7 +140,7 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget { | |||||||
|         // display of $widget in both branches. |         // display of $widget in both branches. | ||||||
|         this.$widget.show(); |         this.$widget.show(); | ||||||
|  |  | ||||||
|         this.watchdog = new EditorWatchdog(BalloonEditor, { |         this.watchdog = new CKEditor.EditorWatchdog(editorClass, { | ||||||
|             // An average number of milliseconds between the last editor errors (defaults to 5000). |             // An average number of milliseconds between the last editor errors (defaults to 5000). | ||||||
|             // When the period of time between errors is lower than that and the crashNumberLimit |             // When the period of time between errors is lower than that and the crashNumberLimit | ||||||
|             // is also reached, the watchdog changes its state to crashedPermanently, and it stops |             // is also reached, the watchdog changes its state to crashedPermanently, and it stops | ||||||
| @@ -169,10 +176,23 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget { | |||||||
|         }); |         }); | ||||||
|  |  | ||||||
|         this.watchdog.setCreator(async (elementOrData, editorConfig) => { |         this.watchdog.setCreator(async (elementOrData, editorConfig) => { | ||||||
|             const editor = await BalloonEditor.create(elementOrData, editorConfig); |             const editor = await editorClass.create(elementOrData, editorConfig); | ||||||
|  |  | ||||||
|             await initSyntaxHighlighting(editor); |             await initSyntaxHighlighting(editor); | ||||||
|  |  | ||||||
|  |             if (isClassicEditor) { | ||||||
|  |                 let $classicToolbarWidget; | ||||||
|  |                 if (!utils.isMobile()) { | ||||||
|  |                     const $parentSplit = this.$widget.parents(".note-split.type-text"); | ||||||
|  |                     $classicToolbarWidget = $parentSplit.find("> .ribbon-container .classic-toolbar-widget"); | ||||||
|  |                 } else { | ||||||
|  |                     $classicToolbarWidget = $("body").find(".classic-toolbar-widget"); | ||||||
|  |                 } | ||||||
|  |                  | ||||||
|  |                 $classicToolbarWidget.empty(); | ||||||
|  |                 $classicToolbarWidget[0].appendChild(editor.ui.view.toolbar.element); | ||||||
|  |             } | ||||||
|  |  | ||||||
|             editor.model.document.on('change:data', () => this.spacedUpdate.scheduleUpdate()); |             editor.model.document.on('change:data', () => this.spacedUpdate.scheduleUpdate()); | ||||||
|  |  | ||||||
|             if (glob.isDev && ENABLE_INSPECTOR) { |             if (glob.isDev && ENABLE_INSPECTOR) { | ||||||
|   | |||||||
| @@ -0,0 +1,30 @@ | |||||||
|  | import { t } from "../../../../services/i18n.js"; | ||||||
|  | import utils from "../../../../services/utils.js"; | ||||||
|  | import OptionsWidget from "../options_widget.js"; | ||||||
|  |  | ||||||
|  | const TPL = ` | ||||||
|  | <div class="options-section"> | ||||||
|  |     <h4>${t("editing.editor_type.label")}</h4> | ||||||
|  |      | ||||||
|  |     <select class="editor-type-select form-select"> | ||||||
|  |         <option value="ckeditor-balloon">${t("editing.editor_type.floating")}</option> | ||||||
|  |         <option value="ckeditor-classic">${t("editing.editor_type.fixed")}</option> | ||||||
|  |     </select> | ||||||
|  | </div>`; | ||||||
|  |  | ||||||
|  | export default class EditorOptions extends OptionsWidget { | ||||||
|  |     doRender() { | ||||||
|  |         this.$widget = $(TPL); | ||||||
|  |         this.$body = $("body"); | ||||||
|  |         this.$editorType = this.$widget.find(".editor-type-select"); | ||||||
|  |         this.$editorType.on('change', async () => { | ||||||
|  |             const newEditorType = this.$editorType.val(); | ||||||
|  |             await this.updateOption('textNoteEditorType', newEditorType); | ||||||
|  |             utils.reloadFrontendApp("editor type change"); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     async optionsLoaded(options) { | ||||||
|  |         this.$editorType.val(options.textNoteEditorType); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										1243
									
								
								src/public/translations/de/translation.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1243
									
								
								src/public/translations/de/translation.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1512,5 +1512,18 @@ | |||||||
|   }, |   }, | ||||||
|   "code_block": { |   "code_block": { | ||||||
|     "word_wrapping": "Word wrapping" |     "word_wrapping": "Word wrapping" | ||||||
|  |   }, | ||||||
|  |   "classic_editor_toolbar": { | ||||||
|  |     "title": "Formatting" | ||||||
|  |   }, | ||||||
|  |   "editor": { | ||||||
|  |     "title": "Editor" | ||||||
|  |   }, | ||||||
|  |   "editing": { | ||||||
|  |     "editor_type": { | ||||||
|  |       "label": "Formatting toolbar", | ||||||
|  |       "floating": "Floating (editing tools appear near the cursor)", | ||||||
|  |       "fixed": "Fixed (editing tools appear in the \"Formatting\" ribbon tab)" | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1508,5 +1508,18 @@ | |||||||
|   }, |   }, | ||||||
|   "code_block": { |   "code_block": { | ||||||
|     "word_wrapping": "Încadrare text" |     "word_wrapping": "Încadrare text" | ||||||
|  |   }, | ||||||
|  |   "classic_editor_toolbar": { | ||||||
|  |     "title": "Formatare" | ||||||
|  |   }, | ||||||
|  |   "editing": { | ||||||
|  |     "editor_type": { | ||||||
|  |       "fixed": "Editor cu bară fixă (uneltele de editare vor apărea în tab-ul „Formatare” din panglică)", | ||||||
|  |       "floating": "Editor cu bară flotantă (uneltele de editare vor apărea lângă cursor)", | ||||||
|  |       "label": "Bară de formatare" | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   "editor": { | ||||||
|  |     "title": "Editor" | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -65,7 +65,8 @@ const ALLOWED_OPTIONS = new Set([ | |||||||
|     'promotedAttributesOpenInRibbon', |     'promotedAttributesOpenInRibbon', | ||||||
|     'editedNotesOpenInRibbon', |     'editedNotesOpenInRibbon', | ||||||
|     'locale', |     'locale', | ||||||
|     'firstDayOfWeek' |     'firstDayOfWeek', | ||||||
|  |     'textNoteEditorType' | ||||||
| ]); | ]); | ||||||
|  |  | ||||||
| function getOptions() { | function getOptions() { | ||||||
| @@ -152,6 +153,10 @@ function getSupportedLocales() { | |||||||
|             "id": "en", |             "id": "en", | ||||||
|             "name": "English" |             "name": "English" | ||||||
|         }, |         }, | ||||||
|  |         { | ||||||
|  |             "id": "de", | ||||||
|  |             "name": "Deutsch" | ||||||
|  |         }, | ||||||
|         { |         { | ||||||
|             "id": "es", |             "id": "es", | ||||||
|             "name": "Español" |             "name": "Español" | ||||||
|   | |||||||
| @@ -420,6 +420,12 @@ function getDefaultKeyboardActions() { | |||||||
|             separator: t("keyboard_actions.ribbon-tabs") |             separator: t("keyboard_actions.ribbon-tabs") | ||||||
|         }, |         }, | ||||||
|      |      | ||||||
|  |         { | ||||||
|  |             actionName: "toggleRibbonTabClassicEditor", | ||||||
|  |             defaultShortcuts: [], | ||||||
|  |             description: t("keyboard_actions.toggle-classic-editor-toolbar"), | ||||||
|  |             scope: "window" | ||||||
|  |         }, | ||||||
|         { |         { | ||||||
|             actionName: "toggleRibbonTabBasicProperties", |             actionName: "toggleRibbonTabBasicProperties", | ||||||
|             defaultShortcuts: [], |             defaultShortcuts: [], | ||||||
|   | |||||||
| @@ -131,7 +131,10 @@ const defaultOptions: DefaultOption[] = [ | |||||||
|             return "default:stackoverflow-dark"; |             return "default:stackoverflow-dark"; | ||||||
|         } |         } | ||||||
|     }, isSynced: false }, |     }, isSynced: false }, | ||||||
|     { name: "codeBlockWordWrap", value: "false", isSynced: true } |     { name: "codeBlockWordWrap", value: "false", isSynced: true }, | ||||||
|  |  | ||||||
|  |     // Text note configuration | ||||||
|  |     { name: "textNoteEditorType", value: "ckeditor-balloon", isSynced: true } | ||||||
| ]; | ]; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|   | |||||||
							
								
								
									
										196
									
								
								translations/de/server.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										196
									
								
								translations/de/server.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,196 @@ | |||||||
|  | { | ||||||
|  |   "keyboard_actions": { | ||||||
|  |     "open-jump-to-note-dialog": "Öffne das Dialogfeld \"Zu Notiz springen\"", | ||||||
|  |     "search-in-subtree": "Suche nach Notizen im Unterbaum der aktuellen Notiz", | ||||||
|  |     "expand-subtree": "Erweitere den Unterbaum der aktuellen Notiz", | ||||||
|  |     "collapse-tree": "Kollabiere den gesamten Notizbaum", | ||||||
|  |     "collapse-subtree": "Kollabiere den Unterbaum der aktuellen Notiz", | ||||||
|  |     "sort-child-notes": "Sortiere untergeordnete Notizen", | ||||||
|  |     "creating-and-moving-notes": "Erstellen und Verschieben von Notizen", | ||||||
|  |     "create-note-into-inbox": "Erstelle eine Notiz im Posteingang (falls definiert) oder in der Tagesnotiz", | ||||||
|  |     "delete-note": "Notiz löschen", | ||||||
|  |     "move-note-up": "Notiz nach oben verschieben", | ||||||
|  |     "move-note-down": "Notiz nach unten verschieben", | ||||||
|  |     "move-note-up-in-hierarchy": "Notiz in der Hierarchie nach oben verschieben", | ||||||
|  |     "move-note-down-in-hierarchy": "Notiz in der Hierarchie nach unten verschieben", | ||||||
|  |     "edit-note-title": "Springe vom Baum zur Notiz-Detailansicht und bearbeite den Titel", | ||||||
|  |     "edit-branch-prefix": "Zeige Dialog zum Bearbeiten des Zweigpräfixes", | ||||||
|  |     "note-clipboard": "Notiz-Zwischenablage", | ||||||
|  |     "copy-notes-to-clipboard": "Kopiere ausgewählte Notizen in die Zwischenablage", | ||||||
|  |     "paste-notes-from-clipboard": "Füge Notizen aus der Zwischenablage in die aktive Notiz ein", | ||||||
|  |     "cut-notes-to-clipboard": "Schneide ausgewählte Notizen in die Zwischenablage", | ||||||
|  |     "select-all-notes-in-parent": "Wähle alle Notizen der aktuellen Notizenebene", | ||||||
|  |     "add-note-above-to-the-selection": "Füge eine Notiz oberhalb zur Auswahl hinzu", | ||||||
|  |     "add-note-below-to-selection": "Füge eine Notiz unterhalb zur Auswahl hinzu", | ||||||
|  |     "duplicate-subtree": "Dupliziere den Unterbaum", | ||||||
|  |     "tabs-and-windows": "Tabs & Fenster", | ||||||
|  |     "open-new-tab": "Öffne einen neuen Tab", | ||||||
|  |     "close-active-tab": "Schließe den aktiven Tab", | ||||||
|  |     "reopen-last-tab": "Öffne den zuletzt geschlossenen Tab", | ||||||
|  |     "activate-next-tab": "Aktiviere den Tab rechts", | ||||||
|  |     "activate-previous-tab": "Aktiviere den Tab links", | ||||||
|  |     "open-new-window": "Öffne ein neues leeres Fenster", | ||||||
|  |     "toggle-tray": "Zeige/verstecke die Anwendung im Systemtray", | ||||||
|  |     "first-tab": "Aktiviere den ersten Tab in der Liste", | ||||||
|  |     "second-tab": "Aktiviere den zweiten Tab in der Liste", | ||||||
|  |     "third-tab": "Aktiviere den dritten Tab in der Liste", | ||||||
|  |     "fourth-tab": "Aktiviere den vierten Tab in der Liste", | ||||||
|  |     "fifth-tab": "Aktiviere den fünften Tab in der Liste", | ||||||
|  |     "sixth-tab": "Aktiviere den sechsten Tab in der Liste", | ||||||
|  |     "seventh-tab": "Aktiviere den siebten Tab in der Liste", | ||||||
|  |     "eight-tab": "Aktiviere den achten Tab in der Liste", | ||||||
|  |     "ninth-tab": "Aktiviere den neunten Tab in der Liste", | ||||||
|  |     "last-tab": "Aktiviere den letzten Tab in der Liste", | ||||||
|  |     "dialogs": "Dialoge", | ||||||
|  |     "show-note-source": "Zeige das Dialogfeld der Notizquelle", | ||||||
|  |     "show-options": "Zeige das Dialogfeld der Optionen", | ||||||
|  |     "show-revisions": "Zeige das Dialogfeld der Notizrevisionen", | ||||||
|  |     "show-recent-changes": "Zeige das Dialogfeld der letzten Änderungen", | ||||||
|  |     "show-sql-console": "Zeige das Dialogfeld der SQL-Konsole", | ||||||
|  |     "show-backend-log": "Zeige das Dialogfeld des Backend-Logs", | ||||||
|  |     "text-note-operations": "Textnotizoperationen", | ||||||
|  |     "add-link-to-text": "Öffne das Dialogfeld zum Hinzufügen eines Links zum Text", | ||||||
|  |     "follow-link-under-cursor": "Folge dem Link, unter dem sich der Cursor befindet", | ||||||
|  |     "insert-date-and-time-to-text": "Füge das aktuelle Datum und die Uhrzeit in den Text ein", | ||||||
|  |     "paste-markdown-into-text": "Füge Markdown aus der Zwischenablage in die Textnotiz ein", | ||||||
|  |     "cut-into-note": "Schneide die Auswahl aus der aktuellen Notiz und erstelle eine Unternotiz mit dem ausgewählten Text", | ||||||
|  |     "add-include-note-to-text": "Öffne das Dialogfeld zum Einfügen einer Notiz", | ||||||
|  |     "edit-readonly-note": "Bearbeite eine schreibgeschützte Notiz", | ||||||
|  |     "attributes-labels-and-relations": "Attribute (Labels & Beziehungen)", | ||||||
|  |     "add-new-label": "Erstelle ein neues Label", | ||||||
|  |     "create-new-relation": "Erstelle eine neue Beziehung", | ||||||
|  |     "ribbon-tabs": "Ribbon-Tabs", | ||||||
|  |     "toggle-basic-properties": "Schalte die Grundattribute um", | ||||||
|  |     "toggle-file-properties": "Schalte die Dateiattribute um", | ||||||
|  |     "toggle-image-properties": "Schalte die Bildattribute um", | ||||||
|  |     "toggle-owned-attributes": "Schalte eigene Attribute um", | ||||||
|  |     "toggle-inherited-attributes": "Schalte vererbte Attribute um", | ||||||
|  |     "toggle-promoted-attributes": "Schalte beworbene Attribute um", | ||||||
|  |     "toggle-link-map": "Schalte die Link-Karte um", | ||||||
|  |     "toggle-note-info": "Schalte Notizinformationen um", | ||||||
|  |     "toggle-note-paths": "Schalte Notizpfade um", | ||||||
|  |     "toggle-similar-notes": "Schalte ähnliche Notizen um", | ||||||
|  |     "other": "Andere", | ||||||
|  |     "toggle-right-pane": "Schalte die Anzeige des rechten Fensters um, das Inhaltsverzeichnis und Markierungen enthält", | ||||||
|  |     "print-active-note": "Drucke die aktive Notiz", | ||||||
|  |     "open-note-externally": "Öffne die Notiz als Datei mit der Standardanwendung", | ||||||
|  |     "render-active-note": "Render (erneut rendern) der aktiven Notiz", | ||||||
|  |     "run-active-note": "Führe den aktiven JavaScript (Frontend/Backend) Notizcode aus", | ||||||
|  |     "toggle-note-hoisting": "Schaltet das Hoisting der aktiven Notiz um", | ||||||
|  |     "unhoist": "Von überall ent-hoisten", | ||||||
|  |     "reload-frontend-app": "Lade die Frontend-App neu", | ||||||
|  |     "open-dev-tools": "Öffne die Entwicklertools", | ||||||
|  |     "toggle-left-note-tree-panel": "Schalte das linke Notizbaum-Panel um", | ||||||
|  |     "toggle-full-screen": "Schalte den Vollbildmodus um", | ||||||
|  |     "zoom-out": "Zoome heraus", | ||||||
|  |     "zoom-in": "Zoome hinein", | ||||||
|  |     "note-navigation": "Notiznavigation", | ||||||
|  |     "reset-zoom-level": "Setze den Zoomlevel zurück", | ||||||
|  |     "copy-without-formatting": "Kopiere den ausgewählten Text ohne Formatierung", | ||||||
|  |     "force-save-revision": "Erzwinge das Erstellen / Speichern einer neuen Notizrevision der aktiven Notiz", | ||||||
|  |     "show-help": "Zeige die eingebaute Hilfe / Cheat-Sheet", | ||||||
|  |     "toggle-book-properties": "Schalte die Buch-Eigenschaften um" | ||||||
|  |   }, | ||||||
|  |   "login": { | ||||||
|  |     "title": "Anmeldung", | ||||||
|  |     "heading": "Trilium Anmeldung", | ||||||
|  |     "incorrect-password": "Das Passwort ist falsch. Bitte versuche es erneut.", | ||||||
|  |     "password": "Passwort", | ||||||
|  |     "remember-me": "Erinnere dich an mich", | ||||||
|  |     "button": "Anmelden" | ||||||
|  |   }, | ||||||
|  |   "set_password": { | ||||||
|  |     "heading": "Passwort festlegen", | ||||||
|  |     "description": "Bevor du Trilium im Web verwenden kannst, musst du zuerst ein Passwort festlegen. Du wirst dieses Passwort dann zur Anmeldung verwenden.", | ||||||
|  |     "password": "Passwort", | ||||||
|  |     "password-confirmation": "Passwortbestätigung", | ||||||
|  |     "button": "Passwort festlegen" | ||||||
|  |   }, | ||||||
|  |   "javascript-required": "Trilium erfordert, dass JavaScript aktiviert ist.", | ||||||
|  |   "setup": { | ||||||
|  |     "heading": "TriliumNext Notizen Setup", | ||||||
|  |     "new-document": "Ich bin ein neuer Benutzer und möchte ein neues Trilium-Dokument für meine Notizen erstellen", | ||||||
|  |     "sync-from-desktop": "Ich habe bereits eine Desktop-Instanz und möchte die Synchronisierung damit einrichten", | ||||||
|  |     "sync-from-server": "Ich habe bereits eine Server-Instanz und möchte die Synchronisierung damit einrichten", | ||||||
|  |     "next": "Weiter", | ||||||
|  |     "init-in-progress": "Dokumenteninitialisierung läuft", | ||||||
|  |     "redirecting": "Du wirst in Kürze zur Anwendung weitergeleitet.", | ||||||
|  |     "title": "Setup" | ||||||
|  |   }, | ||||||
|  |   "setup_sync-from-desktop": { | ||||||
|  |     "heading": "Synchronisation vom Desktop", | ||||||
|  |     "description": "Dieses Setup muss von der Desktop-Instanz aus initiiert werden:", | ||||||
|  |     "step1": "Öffne deine TriliumNext Notes Desktop-Instanz.", | ||||||
|  |     "step2": "Klicke im Trilium-Menü auf Optionen.", | ||||||
|  |     "step3": "Klicke auf die Kategorie Synchronisation.", | ||||||
|  |     "step4": "Ändere die Server-Instanzadresse auf: {{- host}} und klicke auf Speichern.", | ||||||
|  |     "step5": "Klicke auf den Button \"Test-Synchronisation\", um zu überprüfen, ob die Verbindung erfolgreich ist.", | ||||||
|  |     "step6": "Sobald du diese Schritte abgeschlossen hast, klicke auf {{- link}}.", | ||||||
|  |     "step6-here": "hier" | ||||||
|  |   }, | ||||||
|  |   "setup_sync-from-server": { | ||||||
|  |     "heading": "Synchronisation vom Server", | ||||||
|  |     "instructions": "Bitte gib unten die Trilium-Server-Adresse und die Zugangsdaten ein. Dies wird das gesamte Trilium-Dokument vom Server herunterladen und die Synchronisation einrichten. Je nach Dokumentgröße und Verbindungsgeschwindigkeit kann dies eine Weile dauern.", | ||||||
|  |     "server-host": "Trilium Server-Adresse", | ||||||
|  |     "server-host-placeholder": "https://<hostname>:<port>", | ||||||
|  |     "proxy-server": "Proxy-Server (optional)", | ||||||
|  |     "proxy-server-placeholder": "https://<hostname>:<port>", | ||||||
|  |     "note": "Hinweis:", | ||||||
|  |     "proxy-instruction": "Wenn du die Proxy-Einstellung leer lässt, wird der System-Proxy verwendet (nur für die Desktop-Anwendung)", | ||||||
|  |     "password": "Passwort", | ||||||
|  |     "password-placeholder": "Passwort", | ||||||
|  |     "back": "Zurück", | ||||||
|  |     "finish-setup": "Setup abschließen" | ||||||
|  |   }, | ||||||
|  |   "setup_sync-in-progress": { | ||||||
|  |     "heading": "Synchronisation läuft", | ||||||
|  |     "successful": "Die Synchronisation wurde erfolgreich eingerichtet. Es wird eine Weile dauern, bis die erste Synchronisation abgeschlossen ist. Sobald dies erledigt ist, wirst du zur Anmeldeseite weitergeleitet.", | ||||||
|  |     "outstanding-items": "Ausstehende Synchronisationselemente:", | ||||||
|  |     "outstanding-items-default": "N/A" | ||||||
|  |   }, | ||||||
|  |   "share_404": { | ||||||
|  |     "title": "Nicht gefunden", | ||||||
|  |     "heading": "Nicht gefunden" | ||||||
|  |   }, | ||||||
|  |   "share_page": { | ||||||
|  |     "parent": "Eltern:", | ||||||
|  |     "clipped-from": "Diese Notiz wurde ursprünglich von {{- url}} ausgeschnitten", | ||||||
|  |     "child-notes": "Untergeordnete Notizen:", | ||||||
|  |     "no-content": "Diese Notiz hat keinen Inhalt." | ||||||
|  |   }, | ||||||
|  |   "weekdays": { | ||||||
|  |     "monday": "Montag", | ||||||
|  |     "tuesday": "Dienstag", | ||||||
|  |     "wednesday": "Mittwoch", | ||||||
|  |     "thursday": "Donnerstag", | ||||||
|  |     "friday": "Freitag", | ||||||
|  |     "saturday": "Samstag", | ||||||
|  |     "sunday": "Sonntag" | ||||||
|  |   }, | ||||||
|  |   "months": { | ||||||
|  |     "january": "Januar", | ||||||
|  |     "february": "Februar", | ||||||
|  |     "march": "März", | ||||||
|  |     "april": "April", | ||||||
|  |     "may": "Mai", | ||||||
|  |     "june": "Juni", | ||||||
|  |     "july": "Juli", | ||||||
|  |     "august": "August", | ||||||
|  |     "september": "September", | ||||||
|  |     "october": "Oktober", | ||||||
|  |     "november": "November", | ||||||
|  |     "december": "Dezember" | ||||||
|  |   }, | ||||||
|  |   "special_notes": { | ||||||
|  |     "search_prefix": "Suche:" | ||||||
|  |   }, | ||||||
|  |   "code_block": { | ||||||
|  |     "theme_none": "Keine Syntax-Hervorhebung", | ||||||
|  |     "theme_group_light": "Helle Themen", | ||||||
|  |     "theme_group_dark": "Dunkle Themen" | ||||||
|  |   }, | ||||||
|  |   "test_sync": { | ||||||
|  |     "not-configured": "Der Synchronisations-Server-Host ist nicht konfiguriert. Bitte konfiguriere zuerst die Synchronisation.", | ||||||
|  |     "successful": "Die Server-Verbindung wurde erfolgreich hergestellt, die Synchronisation wurde gestartet." | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -89,7 +89,8 @@ | |||||||
|     "copy-without-formatting": "Copy selected text without formatting", |     "copy-without-formatting": "Copy selected text without formatting", | ||||||
|     "force-save-revision": "Force creating / saving new note revision of the active note", |     "force-save-revision": "Force creating / saving new note revision of the active note", | ||||||
|     "show-help": "Shows built-in Help / cheatsheet", |     "show-help": "Shows built-in Help / cheatsheet", | ||||||
|     "toggle-book-properties": "Toggle Book Properties" |     "toggle-book-properties": "Toggle Book Properties", | ||||||
|  |     "toggle-classic-editor-toolbar": "Toggle the Formatting tab for the editor with fixed toolbar" | ||||||
|   }, |   }, | ||||||
|   "login": { |   "login": { | ||||||
|     "title": "Login", |     "title": "Login", | ||||||
|   | |||||||
| @@ -89,7 +89,8 @@ | |||||||
|     "toggle-tray": "Afișează/ascunde aplicația din tray-ul de sistem", |     "toggle-tray": "Afișează/ascunde aplicația din tray-ul de sistem", | ||||||
|     "unhoist": "Defocalizează complet", |     "unhoist": "Defocalizează complet", | ||||||
|     "zoom-in": "Mărește zoom-ul", |     "zoom-in": "Mărește zoom-ul", | ||||||
|     "zoom-out": "Micșorează zoom-ul" |     "zoom-out": "Micșorează zoom-ul", | ||||||
|  |     "toggle-classic-editor-toolbar": "Comută tab-ul „Formatare” pentru editorul cu bară fixă" | ||||||
|   }, |   }, | ||||||
|   "login": { |   "login": { | ||||||
|     "button": "Autentifică", |     "button": "Autentifică", | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user