mirror of
				https://github.com/TriliumNext/Notes.git
				synced 2025-10-30 20:41:33 +08:00 
			
		
		
		
	Merge branch 'develop' into siriusxt_patch
This commit is contained in:
		
						commit
						ce40c74e83
					
				| @ -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)  | ||||
| 
 | ||||
| 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 | ||||
| 
 | ||||
| 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 CopyImageReferenceButton from "../widgets/floating_buttons/copy_image_reference_button.js"; | ||||
| import ScrollPaddingWidget from "../widgets/scroll_padding.js"; | ||||
| import ClassicEditorToolbar from "../widgets/ribbon_widgets/classic_editor_toolbar.js"; | ||||
| 
 | ||||
| export default class DesktopLayout { | ||||
|     constructor(customWidgets) { | ||||
| @ -140,6 +141,7 @@ export default class DesktopLayout { | ||||
|                                             // 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".
 | ||||
|                                             // promoted attributes should always win.
 | ||||
|                                             .ribbon(new ClassicEditorToolbar()) | ||||
|                                             .ribbon(new PromotedAttributesWidget()) | ||||
|                                             .ribbon(new ScriptExecutorWidget()) | ||||
|                                             .ribbon(new SearchDefinitionWidget()) | ||||
|  | ||||
| @ -23,6 +23,7 @@ import LauncherContainer from "../widgets/containers/launcher_container.js"; | ||||
| import RootContainer from "../widgets/containers/root_container.js"; | ||||
| import SharedInfoWidget from "../widgets/shared_info.js"; | ||||
| import PromotedAttributesWidget from "../widgets/ribbon_widgets/promoted_attributes.js"; | ||||
| import ClassicEditorToolbar from "../widgets/ribbon_widgets/classic_editor_toolbar.js"; | ||||
| 
 | ||||
| const MOBILE_CSS = ` | ||||
| <style> | ||||
| @ -167,6 +168,7 @@ export default class MobileLayout { | ||||
|                             .child(new NoteListWidget()) | ||||
|                             .child(new FilePropertiesWidget().css('font-size','smaller')) | ||||
|                     ) | ||||
|                     .child(new ClassicEditorToolbar()) | ||||
|                 ) | ||||
|                 .child(new ProtectedSessionPasswordDialog()) | ||||
|                 .child(new ConfirmDialog()) | ||||
|  | ||||
| @ -527,6 +527,58 @@ function downloadSvg(nameWithoutExtension, svgContent) { | ||||
|     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 { | ||||
|     reloadFrontendApp, | ||||
|     parseDate, | ||||
| @ -567,5 +619,7 @@ export default { | ||||
|     areObjectsEqual, | ||||
|     copyHtmlToClipboard, | ||||
|     createImageSrcUrl, | ||||
|     downloadSvg | ||||
|     downloadSvg, | ||||
|     compareVersions, | ||||
|     isUpdateAvailable | ||||
| }; | ||||
|  | ||||
| @ -347,8 +347,7 @@ export default class AttributeEditorWidget extends NoteContextAwareWidget { | ||||
| 
 | ||||
|         this.$editor.on("click", e => this.handleEditorClick(e)); | ||||
| 
 | ||||
|         /** @property {BalloonEditor} */ | ||||
|         this.textEditor = await BalloonEditor.create(this.$editor[0], editorConfig); | ||||
|         this.textEditor = await CKEditor.BalloonEditor.create(this.$editor[0], editorConfig); | ||||
|         this.textEditor.model.document.on('change:data', () => this.dataChanged()); | ||||
|         this.textEditor.editing.view.document.on('enter', (event, data) => { | ||||
|             // 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
 | ||||
|         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() { | ||||
|  | ||||
| @ -333,7 +333,8 @@ export default class GlobalMenuWidget extends BasicWidget { | ||||
| 
 | ||||
|         const latestVersion = await this.fetchLatestVersion(); | ||||
|         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.`); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -1,5 +1,6 @@ | ||||
| import { t } from "../../services/i18n.js"; | ||||
| import BasicWidget from "../basic_widget.js"; | ||||
| import utils from "../../services/utils.js"; | ||||
| 
 | ||||
| const TPL = ` | ||||
| <div style="display: none;"> | ||||
| @ -34,6 +35,6 @@ export default class UpdateAvailableWidget extends BasicWidget { | ||||
|     } | ||||
| 
 | ||||
|     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(); | ||||
| 
 | ||||
|         for (const ribbonWidget of this.ribbonWidgets) { | ||||
|             const ret = ribbonWidget.getTitle(note); | ||||
|             const ret = await ribbonWidget.getTitle(note); | ||||
| 
 | ||||
|             if (!ret.show) { | ||||
|                 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() { | ||||
|         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 LocalizationOptions from "./options/appearance/i18n.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">
 | ||||
|     <style> | ||||
| @ -68,6 +69,7 @@ const CONTENT_WIDGETS = { | ||||
|     ], | ||||
|     _optionsShortcuts: [ KeyboardShortcutsOptions ], | ||||
|     _optionsTextNotes: [ | ||||
|         EditorOptions, | ||||
|         HeadingStyleOptions, | ||||
|         TableOfContentsOptions, | ||||
|         HighlightsListOptions, | ||||
|  | ||||
| @ -12,7 +12,6 @@ import appContext from "../../components/app_context.js"; | ||||
| import dialogService from "../../services/dialog.js"; | ||||
| import { initSyntaxHighlighting } from "./ckeditor/syntax_highlight.js"; | ||||
| import options from "../../services/options.js"; | ||||
| import { isSyntaxHighlightEnabled } from "../../services/syntax_highlight.js"; | ||||
| 
 | ||||
| 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 { | ||||
|     static getType() { return "editableText"; } | ||||
| 
 | ||||
| @ -125,6 +130,8 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget { | ||||
| 
 | ||||
|     async initEditor() { | ||||
|         await libraryLoader.requireLibrary(libraryLoader.CKEDITOR); | ||||
|         const isClassicEditor = (options.get("textNoteEditorType") === "ckeditor-classic") | ||||
|         const editorClass = (isClassicEditor ? CKEditor.DecoupledEditor : CKEditor.BalloonEditor); | ||||
| 
 | ||||
|         const codeBlockLanguages = buildListOfLanguages(); | ||||
| 
 | ||||
| @ -133,7 +140,7 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget { | ||||
|         // display of $widget in both branches.
 | ||||
|         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).
 | ||||
|             // 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
 | ||||
| @ -169,10 +176,23 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget { | ||||
|         }); | ||||
| 
 | ||||
|         this.watchdog.setCreator(async (elementOrData, editorConfig) => { | ||||
|             const editor = await BalloonEditor.create(elementOrData, editorConfig); | ||||
|             const editor = await editorClass.create(elementOrData, editorConfig); | ||||
| 
 | ||||
|             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()); | ||||
| 
 | ||||
|             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": { | ||||
|     "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": { | ||||
|     "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', | ||||
|     'editedNotesOpenInRibbon', | ||||
|     'locale', | ||||
|     'firstDayOfWeek' | ||||
|     'firstDayOfWeek', | ||||
|     'textNoteEditorType' | ||||
| ]); | ||||
| 
 | ||||
| function getOptions() { | ||||
| @ -152,6 +153,10 @@ function getSupportedLocales() { | ||||
|             "id": "en", | ||||
|             "name": "English" | ||||
|         }, | ||||
|         { | ||||
|             "id": "de", | ||||
|             "name": "Deutsch" | ||||
|         }, | ||||
|         { | ||||
|             "id": "es", | ||||
|             "name": "Español" | ||||
|  | ||||
| @ -420,6 +420,12 @@ function getDefaultKeyboardActions() { | ||||
|             separator: t("keyboard_actions.ribbon-tabs") | ||||
|         }, | ||||
|      | ||||
|         { | ||||
|             actionName: "toggleRibbonTabClassicEditor", | ||||
|             defaultShortcuts: [], | ||||
|             description: t("keyboard_actions.toggle-classic-editor-toolbar"), | ||||
|             scope: "window" | ||||
|         }, | ||||
|         { | ||||
|             actionName: "toggleRibbonTabBasicProperties", | ||||
|             defaultShortcuts: [], | ||||
|  | ||||
| @ -131,7 +131,10 @@ const defaultOptions: DefaultOption[] = [ | ||||
|             return "default:stackoverflow-dark"; | ||||
|         } | ||||
|     }, 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", | ||||
|     "force-save-revision": "Force creating / saving new note revision of the active note", | ||||
|     "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": { | ||||
|     "title": "Login", | ||||
|  | ||||
| @ -89,7 +89,8 @@ | ||||
|     "toggle-tray": "Afișează/ascunde aplicația din tray-ul de sistem", | ||||
|     "unhoist": "Defocalizează complet", | ||||
|     "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": { | ||||
|     "button": "Autentifică", | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 SiriusXT
						SiriusXT