Merge branch 'develop' into siriusxt_patch

This commit is contained in:
SiriusXT 2024-11-11 18:26:07 +08:00
commit ce40c74e83
24 changed files with 1751 additions and 18 deletions

View File

@ -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
View 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;
};
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -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())

View File

@ -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())

View File

@ -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
};

View File

@ -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() {

View File

@ -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.`);
}

View File

@ -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));
}
}

View File

@ -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)
}

View File

@ -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;
}
}

View File

@ -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,

View File

@ -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) {

View File

@ -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);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -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)"
}
}
}

View File

@ -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"
}
}

View File

@ -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"

View File

@ -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: [],

View File

@ -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
View 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."
}
}

View File

@ -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",

View File

@ -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ă",