diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index a573d1938c..fad12709d3 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,5 +1,7 @@ # Trilium Notes - AI Coding Agent Instructions +> **Note**: When updating this file, also update `CLAUDE.md` in the repository root to keep both AI coding assistants in sync. + ## Project Overview Trilium Notes is a hierarchical note-taking application with advanced features like synchronization, scripting, and rich text editing. Built as a TypeScript monorepo using pnpm, it implements a three-layer caching architecture (Becca/Froca/Shaca) with a widget-based UI system and supports extensive user scripting capabilities. @@ -115,6 +117,15 @@ class MyNoteWidget extends NoteContextAwareWidget { **Important**: Widgets use jQuery (`this.$widget`) for DOM manipulation. Don't mix React patterns here. +### Reusable Preact Components +Common UI components are available in `apps/client/src/widgets/react/` — prefer reusing these over creating custom implementations: +- `NoItems` - Empty state placeholder with icon and message (use for "no results", "too many items", error states) +- `ActionButton` - Consistent button styling with icon support +- `FormTextBox` - Text input with validation and controlled input handling +- `Slider` - Range slider with label +- `Checkbox`, `RadioButton` - Form controls +- `CollapsibleSection` - Expandable content sections + ## Development Workflow ### Running & Testing @@ -320,9 +331,28 @@ Trilium provides powerful user scripting capabilities: - Use translation system via `t()` function - Automatic pluralization: Add `_other` suffix to translation keys (e.g., `item` and `item_other` for singular/plural) - When a translated string contains **interpolated components** (e.g. links, note references) whose order may vary across languages, use `` from `react-i18next` instead of `t()`. This lets translators reorder components freely (e.g. `" in "` vs `"in , "`) +- When adding a new locale, follow the step-by-step guide in `docs/Developer Guide/Developer Guide/Concepts/Internationalisation Translations/Adding a new locale.md` + +#### Client vs Server Translation Usage +- **Client-side**: `import { t } from "../services/i18n"` with keys in `apps/client/src/translations/en/translation.json` +- **Server-side**: `import { t } from "i18next"` with keys in `apps/server/src/assets/translations/en/server.json` +- **Interpolation**: Use `{{variable}}` for normal interpolation; use `{{- variable}}` (with hyphen) for **unescaped** interpolation when the value contains special characters like quotes that shouldn't be HTML-escaped + +### Storing User Preferences +- **Do not use `localStorage`** for user preferences — Trilium has a synced options system that persists across devices +- To add a new user preference: + 1. Add the option type to `OptionDefinitions` in `packages/commons/src/lib/options_interface.ts` + 2. Add a default value in `apps/server/src/services/options_init.ts` in the `defaultOptions` array + 3. **Whitelist the option** in `apps/server/src/routes/api/options.ts` by adding it to `ALLOWED_OPTIONS` (required for client updates) + 4. Use `useTriliumOption("optionName")` hook in React components to read/write the option +- Available hooks: `useTriliumOption` (string), `useTriliumOptionBool`, `useTriliumOptionInt`, `useTriliumOptionJson` +- See `docs/Developer Guide/Developer Guide/Concepts/Options/Creating a new option.md` for detailed documentation ## Testing Conventions +- **Write concise tests**: Group related assertions together in a single test case rather than creating many one-shot tests +- **Extract and test business logic**: When adding pure business logic (e.g., data transformations, migrations, validations), extract it as a separate function and always write unit tests for it + ```typescript // ETAPI test pattern describe("etapi/feature", () => { diff --git a/CLAUDE.md b/CLAUDE.md index acec08b8ae..1b90b02881 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -2,6 +2,8 @@ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. +> **Note**: When updating this file, also update `.github/copilot-instructions.md` to keep both AI coding assistants in sync. + ## Overview Trilium Notes is a hierarchical note-taking application with advanced features like synchronization, scripting, and rich text editing. It's built as a TypeScript monorepo using pnpm, with multiple applications and shared packages. @@ -66,6 +68,15 @@ Frontend uses a widget system (`apps/client/src/widgets/`): - `RightPanelWidget` - Widgets displayed in the right panel - Type-specific widgets in `type_widgets/` directory +#### Reusable Preact Components +Common UI components are available in `apps/client/src/widgets/react/` — prefer reusing these over creating custom implementations: +- `NoItems` - Empty state placeholder with icon and message (use for "no results", "too many items", error states) +- `ActionButton` - Consistent button styling with icon support +- `FormTextBox` - Text input with validation and controlled input handling +- `Slider` - Range slider with label +- `Checkbox`, `RadioButton` - Form controls +- `CollapsibleSection` - Expandable content sections + #### API Architecture - **Internal API**: REST endpoints in `apps/server/src/routes/api/` - **ETAPI**: External API for third-party integrations (`apps/server/src/etapi/`) @@ -108,6 +119,8 @@ Trilium supports multiple note types, each with specialized widgets: - Client tests can run in parallel - E2E tests use Playwright for both server and desktop apps - Build validation tests check artifact integrity +- **Write concise tests**: Group related assertions together in a single test case rather than creating many one-shot tests +- **Extract and test business logic**: When adding pure business logic (e.g., data transformations, migrations, validations), extract it as a separate function and always write unit tests for it ### Scripting System Trilium provides powerful user scripting capabilities: @@ -121,6 +134,18 @@ Trilium provides powerful user scripting capabilities: - **Only add new translation keys to `en/translation.json`** — translations for other languages are managed via Weblate and will be contributed by the community - Third-party components (e.g., mind-map context menu) should use i18next `t()` for their labels, with the English strings added to `en/translation.json` under a dedicated namespace (e.g., `"mind-map"`) - When a translated string contains **interpolated components** (e.g. links, note references) whose order may vary across languages, use `` from `react-i18next` instead of `t()`. This lets translators reorder components freely (e.g. `" in "` vs `"in , "`) +- When adding a new locale, follow the step-by-step guide in `docs/Developer Guide/Developer Guide/Concepts/Internationalisation Translations/Adding a new locale.md` +- **Server-side translations** (e.g. hidden subtree titles) go in `apps/server/src/assets/translations/en/server.json`, not in the client `translation.json` + +#### Client vs Server Translation Usage +- **Client-side**: `import { t } from "../services/i18n"` with keys in `apps/client/src/translations/en/translation.json` +- **Server-side**: `import { t } from "i18next"` with keys in `apps/server/src/assets/translations/en/server.json` +- **Interpolation**: Use `{{variable}}` for normal interpolation; use `{{- variable}}` (with hyphen) for **unescaped** interpolation when the value contains special characters like quotes that shouldn't be HTML-escaped + +### Electron Desktop App +- Desktop entry point: `apps/desktop/src/main.ts`, window management: `apps/server/src/services/window.ts` +- IPC communication: use `electron.ipcMain.on(channel, handler)` on server side, `electron.ipcRenderer.send(channel, data)` on client side +- Electron-only features should check `isElectron()` from `apps/client/src/services/utils.ts` (client) or `utils.isElectron` (server) ### Security Considerations - Per-note encryption with granular protected sessions @@ -132,6 +157,16 @@ Trilium provides powerful user scripting capabilities: - **Do not use `crypto.randomUUID()`** or other Web Crypto APIs that require secure contexts - Trilium can run over HTTP, not just HTTPS - Use `randomString()` from `apps/client/src/services/utils.ts` for generating IDs instead +### Storing User Preferences +- **Do not use `localStorage`** for user preferences — Trilium has a synced options system that persists across devices +- To add a new user preference: + 1. Add the option type to `OptionDefinitions` in `packages/commons/src/lib/options_interface.ts` + 2. Add a default value in `apps/server/src/services/options_init.ts` in the `defaultOptions` array + 3. **Whitelist the option** in `apps/server/src/routes/api/options.ts` by adding it to `ALLOWED_OPTIONS` (required for client updates) + 4. Use `useTriliumOption("optionName")` hook in React components to read/write the option +- Available hooks: `useTriliumOption` (string), `useTriliumOptionBool`, `useTriliumOptionInt`, `useTriliumOptionJson` +- See `docs/Developer Guide/Developer Guide/Concepts/Options/Creating a new option.md` for detailed documentation + ### Shared Types Policy - Types shared between client and server belong in `@triliumnext/commons` (`packages/commons/src/lib/`) - Import shared types directly from `@triliumnext/commons` - do not re-export them from app-specific modules @@ -152,6 +187,20 @@ Trilium provides powerful user scripting capabilities: - Create new package in `packages/` following existing plugin structure - Register in `packages/ckeditor5/src/plugins.ts` +### Adding Hidden System Notes +The hidden subtree (`_hidden`) contains system notes with predictable IDs (prefixed with `_`). Defined in `apps/server/src/services/hidden_subtree.ts` via the `HiddenSubtreeItem` interface from `@triliumnext/commons`. + +1. Add the note definition to `buildHiddenSubtreeDefinition()` in `apps/server/src/services/hidden_subtree.ts` +2. Add a translation key for the title in `apps/server/src/assets/translations/en/server.json` under `"hidden-subtree"` +3. The note is auto-created on startup by `checkHiddenSubtree()` — uses deterministic IDs so all sync cluster instances generate the same structure +4. Key properties: `id` (must start with `_`), `title`, `type`, `icon` (format: `bx-icon-name` without `bx ` prefix), `attributes`, `children`, `content` +5. Use `enforceAttributes: true` to keep attributes in sync, `enforceBranches: true` for correct placement, `enforceDeleted: true` to remove deprecated notes +6. For launcher bar entries, see `hidden_subtree_launcherbar.ts`; for templates, see `hidden_subtree_templates.ts` + +### Writing to Notes from Server Services +- `note.setContent()` requires a CLS (Continuation Local Storage) context — wrap calls in `cls.init(() => { ... })` (from `apps/server/src/services/cls.ts`) +- Operations called from Express routes already have CLS context; standalone services (schedulers, Electron IPC handlers) do not + ### Adding New LLM Tools Tools are defined using `defineTools()` in `apps/server/src/services/llm/tools/` and automatically registered for both the LLM chat and MCP server. diff --git a/apps/build-docs/package.json b/apps/build-docs/package.json index 2b21df5714..3be2fb44ac 100644 --- a/apps/build-docs/package.json +++ b/apps/build-docs/package.json @@ -16,11 +16,11 @@ "license": "AGPL-3.0-only", "packageManager": "pnpm@10.33.0", "devDependencies": { - "@redocly/cli": "2.25.3", + "@redocly/cli": "2.26.0", "archiver": "7.0.1", "fs-extra": "11.3.4", "js-yaml": "4.1.1", "typedoc": "0.28.18", - "typedoc-plugin-missing-exports": "4.1.2" + "typedoc-plugin-missing-exports": "4.1.3" } } diff --git a/apps/client/package.json b/apps/client/package.json index 38cdd1291a..7cff4e1ed0 100644 --- a/apps/client/package.json +++ b/apps/client/package.json @@ -34,15 +34,15 @@ "@triliumnext/highlightjs": "workspace:*", "@triliumnext/share-theme": "workspace:*", "@triliumnext/split.js": "workspace:*", - "@univerjs/preset-sheets-conditional-formatting": "0.19.0", - "@univerjs/preset-sheets-core": "0.19.0", - "@univerjs/preset-sheets-data-validation": "0.19.0", - "@univerjs/preset-sheets-filter": "0.19.0", - "@univerjs/preset-sheets-find-replace": "0.19.0", - "@univerjs/preset-sheets-note": "0.19.0", - "@univerjs/preset-sheets-sort": "0.19.0", - "@univerjs/presets": "0.19.0", - "@zumer/snapdom": "2.7.0", + "@univerjs/preset-sheets-conditional-formatting": "0.20.0", + "@univerjs/preset-sheets-core": "0.20.0", + "@univerjs/preset-sheets-data-validation": "0.20.0", + "@univerjs/preset-sheets-filter": "0.20.0", + "@univerjs/preset-sheets-find-replace": "0.20.0", + "@univerjs/preset-sheets-note": "0.20.0", + "@univerjs/preset-sheets-sort": "0.20.0", + "@univerjs/presets": "0.20.0", + "@zumer/snapdom": "2.8.0", "autocomplete.js": "0.38.1", "bootstrap": "5.3.8", "boxicons": "2.1.4", @@ -52,20 +52,20 @@ "dompurify": "3.3.3", "draggabilly": "3.0.0", "force-graph": "1.51.2", - "i18next": "26.0.3", + "i18next": "26.0.4", "i18next-http-backend": "3.0.4", "jquery": "4.0.0", "jquery.fancytree": "2.38.5", "jsplumb": "2.15.6", - "katex": "0.16.44", + "katex": "0.16.45", "leaflet": "1.9.4", "leaflet-gpx": "2.2.0", "mark.js": "8.11.1", - "marked": "17.0.5", + "marked": "18.0.0", "mermaid": "11.14.0", "mind-elixir": "5.10.0", "panzoom": "9.4.4", - "preact": "10.29.0", + "preact": "10.29.1", "react-i18next": "17.0.2", "react-window": "2.2.7", "reveal.js": "6.0.0", @@ -76,7 +76,7 @@ }, "devDependencies": { "@ckeditor/ckeditor5-inspector": "5.0.0", - "@prefresh/vite": "2.4.12", + "@prefresh/vite": "3.0.0", "@types/bootstrap": "5.2.10", "@types/jquery": "4.0.0", "@types/leaflet": "1.9.21", @@ -87,6 +87,6 @@ "happy-dom": "20.8.9", "lightningcss": "1.32.0", "script-loader": "0.7.2", - "vite-plugin-static-copy": "4.0.0" + "vite-plugin-static-copy": "4.0.1" } } diff --git a/apps/client/src/components/app_context.ts b/apps/client/src/components/app_context.ts index d731f03382..7019617714 100644 --- a/apps/client/src/components/app_context.ts +++ b/apps/client/src/components/app_context.ts @@ -1,10 +1,11 @@ import type { CKTextEditor } from "@triliumnext/ckeditor5"; import type CodeMirror from "@triliumnext/codemirror"; -import { SqlExecuteResponse } from "@triliumnext/commons"; +import { type LOCALE_IDS, SqlExecuteResponse } from "@triliumnext/commons"; import type { NativeImage, TouchBar } from "electron"; import { ColumnComponent } from "tabulator-tables"; import type { Attribute } from "../services/attribute_parser.js"; +import bundleService from "../services/bundle.js"; import froca from "../services/froca.js"; import { initLocale, t } from "../services/i18n.js"; import keyboardActionsService from "../services/keyboard_actions.js"; @@ -563,7 +564,7 @@ export class AppContext extends Component { */ async earlyInit() { await options.initializedPromise; - await initLocale(); + await initLocale((options.get("locale") || "en") as LOCALE_IDS); } setLayout(layout: Layout) { @@ -578,7 +579,6 @@ export class AppContext extends Component { this.tabManager.loadTabs(); - const bundleService = (await import("../services/bundle.js")).default; setTimeout(() => bundleService.executeStartupBundles(), 2000); } diff --git a/apps/client/src/desktop.ts b/apps/client/src/desktop.ts index 6f22d3fc7b..bb1f859809 100644 --- a/apps/client/src/desktop.ts +++ b/apps/client/src/desktop.ts @@ -54,7 +54,7 @@ function initOnElectron() { const currentWindow = electronRemote.getCurrentWindow(); const style = window.getComputedStyle(document.body); - initDarkOrLightMode(style); + initDarkOrLightMode(); initTransparencyEffects(style, currentWindow); initFullScreenDetection(currentWindow); @@ -119,11 +119,11 @@ function initTransparencyEffects(style: CSSStyleDeclaration, currentWindow: Elec * * @param style the root CSS element to read variables from. */ -function initDarkOrLightMode(style: CSSStyleDeclaration) { +function initDarkOrLightMode() { let themeSource: typeof nativeTheme.themeSource = "system"; - const themeStyle = style.getPropertyValue("--theme-style"); - if (style.getPropertyValue("--theme-style-auto") !== "true" && (themeStyle === "light" || themeStyle === "dark")) { + const themeStyle = window.glob.getThemeStyle(); + if (themeStyle !== "auto") { themeSource = themeStyle; } diff --git a/apps/client/src/entities/fnote.ts b/apps/client/src/entities/fnote.ts index 12fd311bec..a30a83975a 100644 --- a/apps/client/src/entities/fnote.ts +++ b/apps/client/src/entities/fnote.ts @@ -1,5 +1,6 @@ import { getNoteIcon } from "@triliumnext/commons"; +import bundleService from "../services/bundle.js"; import cssClassManager from "../services/css_class_manager.js"; import type { Froca } from "../services/froca-interface.js"; import noteAttributeCache from "../services/note_attribute_cache.js"; @@ -235,6 +236,16 @@ export default class FNote { return this.hasAttribute("label", "archived"); } + /** + * Returns true if the note's metadata (title, icon) should not be editable. + * This applies to system notes like options, help, and launch bar configuration. + */ + get isMetadataReadOnly() { + return utils.isLaunchBarConfig(this.noteId) + || this.noteId.startsWith("_help_") + || this.noteId.startsWith("_options"); + } + getChildNoteIds() { return this.children; } @@ -1014,7 +1025,6 @@ export default class FNote { const env = this.getScriptEnv(); if (env === "frontend") { - const bundleService = (await import("../services/bundle.js")).default; return await bundleService.getAndExecuteBundle(this.noteId); } else if (env === "backend") { await server.post(`script/run/${this.noteId}`); diff --git a/apps/client/src/index.ts b/apps/client/src/index.ts index fba6e17d7e..720d3eb59c 100644 --- a/apps/client/src/index.ts +++ b/apps/client/src/index.ts @@ -1,3 +1,5 @@ +import { getThemeStyle } from "./services/theme"; + async function bootstrap() { showSplash(); await setupGlob(); @@ -38,6 +40,7 @@ async function setupGlob() { ...json, activeDialog: null }; + window.glob.getThemeStyle = getThemeStyle; } async function loadBootstrapCss() { @@ -49,31 +52,65 @@ async function loadBootstrapCss() { } } -function loadStylesheets() { - const { device, assetPath, themeCssUrl, themeUseNextAsBase } = window.glob; +type StylesheetRef = { + href: string; + media?: string; +}; - const cssToLoad: string[] = []; - if (device !== "print") { - cssToLoad.push(`${assetPath}/stylesheets/ckeditor-theme.css`); - cssToLoad.push(`api/fonts`); - cssToLoad.push(`${assetPath}/stylesheets/theme-light.css`); - if (themeCssUrl) { - cssToLoad.push(themeCssUrl); - } - if (themeUseNextAsBase === "next") { - cssToLoad.push(`${assetPath}/stylesheets/theme-next.css`); - } else if (themeUseNextAsBase === "next-dark") { - cssToLoad.push(`${assetPath}/stylesheets/theme-next-dark.css`); - } else if (themeUseNextAsBase === "next-light") { - cssToLoad.push(`${assetPath}/stylesheets/theme-next-light.css`); - } - cssToLoad.push(`${assetPath}/stylesheets/style.css`); +function getConfiguredThemeStylesheets(stylesheetsPath: string, theme: string, customThemeCssUrl?: string) { + if (theme === "auto") { + return [{ href: `${stylesheetsPath}/theme-dark.css`, media: "(prefers-color-scheme: dark)" }]; } - for (const href of cssToLoad) { + if (theme === "dark") { + return [{ href: `${stylesheetsPath}/theme-dark.css` }]; + } + + if (theme === "next") { + return [ + { href: `${stylesheetsPath}/theme-next-light.css` }, + { href: `${stylesheetsPath}/theme-next-dark.css`, media: "(prefers-color-scheme: dark)" } + ]; + } + + if (theme === "next-light") { + return [{ href: `${stylesheetsPath}/theme-next-light.css` }]; + } + + if (theme === "next-dark") { + return [{ href: `${stylesheetsPath}/theme-next-dark.css` }]; + } + + if (theme !== "light" && customThemeCssUrl) { + return [{ href: customThemeCssUrl }]; + } + + return []; +} + +function loadStylesheets() { + const { device, assetPath, theme, themeBase, customThemeCssUrl } = window.glob; + const stylesheetsPath = `${assetPath}/stylesheets`; + + const cssToLoad: StylesheetRef[] = []; + if (device !== "print") { + cssToLoad.push({ href: `${stylesheetsPath}/ckeditor-theme.css` }); + cssToLoad.push({ href: `api/fonts` }); + cssToLoad.push({ href: `${stylesheetsPath}/theme-light.css` }); + cssToLoad.push(...getConfiguredThemeStylesheets(stylesheetsPath, theme, customThemeCssUrl)); + if (themeBase) { + cssToLoad.push(...getConfiguredThemeStylesheets(stylesheetsPath, themeBase)); + } + cssToLoad.push({ href: `${stylesheetsPath}/style.css` }); + } + + for (const { href, media } of cssToLoad) { const linkEl = document.createElement("link"); linkEl.href = href; linkEl.rel = "stylesheet"; + if (media) { + linkEl.media = media; + } document.head.appendChild(linkEl); } } diff --git a/apps/client/src/menus/electron_context_menu.ts b/apps/client/src/menus/electron_context_menu.ts index 6baba6a951..a894cebfc3 100644 --- a/apps/client/src/menus/electron_context_menu.ts +++ b/apps/client/src/menus/electron_context_menu.ts @@ -1,12 +1,14 @@ -import utils from "../services/utils.js"; -import options from "../services/options.js"; -import zoomService from "../components/zoom.js"; -import contextMenu, { type MenuItem } from "./context_menu.js"; -import { t } from "../services/i18n.js"; -import server from "../services/server.js"; -import * as clipboardExt from "../services/clipboard_ext.js"; import type { BrowserWindow } from "electron"; -import type { CommandNames, AppContext } from "../components/app_context.js"; + +import type { CommandNames } from "../components/app_context.js"; +import appContext from "../components/app_context.js"; +import zoomService from "../components/zoom.js"; +import * as clipboardExt from "../services/clipboard_ext.js"; +import { t } from "../services/i18n.js"; +import options from "../services/options.js"; +import server from "../services/server.js"; +import utils from "../services/utils.js"; +import contextMenu, { type MenuItem } from "./context_menu.js"; function setupContextMenu() { const electron = utils.dynamicRequire("electron"); @@ -15,8 +17,6 @@ function setupContextMenu() { // FIXME: Remove typecast once Electron is properly integrated. const { webContents } = remote.getCurrentWindow() as BrowserWindow; - let appContext: AppContext; - webContents.on("context-menu", (event, params) => { const { editFlags } = params; const hasText = params.selectionText.trim().length > 0; @@ -38,7 +38,7 @@ function setupContextMenu() { items.push({ title: t("electron_context_menu.add-term-to-dictionary", { term: params.misspelledWord }), uiIcon: "bx bx-plus", - handler: () => webContents.session.addWordToSpellCheckerDictionary(params.misspelledWord) + handler: () => electron.ipcRenderer.send("add-word-to-dictionary", params.misspelledWord) }); items.push({ kind: "separator" }); @@ -141,7 +141,7 @@ function setupContextMenu() { } // Replace the placeholder with the real search keyword. - let searchUrl = searchEngineUrl.replace("{keyword}", encodeURIComponent(params.selectionText)); + const searchUrl = searchEngineUrl.replace("{keyword}", encodeURIComponent(params.selectionText)); items.push({ kind: "separator" }); @@ -155,10 +155,6 @@ function setupContextMenu() { title: t("electron_context_menu.search_in_trilium", { term: shortenedSelection }), uiIcon: "bx bx-search", handler: async () => { - if (!appContext) { - appContext = (await import("../components/app_context.js")).default; - } - await appContext.triggerCommand("searchNotes", { searchString: params.selectionText }); diff --git a/apps/client/src/print.tsx b/apps/client/src/print.tsx index dc7817d9b5..c943413c49 100644 --- a/apps/client/src/print.tsx +++ b/apps/client/src/print.tsx @@ -4,6 +4,7 @@ import { useCallback, useLayoutEffect, useRef } from "preact/hooks"; import FNote from "./entities/fnote"; import content_renderer from "./services/content_renderer"; import { applyInlineMermaid } from "./services/content_renderer_text"; +import froca from "./services/froca"; import { dynamicRequire, isElectron } from "./services/utils"; import { CustomNoteList, useNoteViewType } from "./widgets/collections/NoteList"; @@ -30,7 +31,6 @@ async function main() { if (!noteId) return; await import("./print.css"); - const froca = (await import("./services/froca")).default; const note = await froca.getNote(noteId); const bodyWrapper = document.createElement("div"); diff --git a/apps/client/src/services/attributes.spec.ts b/apps/client/src/services/attributes.spec.ts index 7a949eebc6..f9caa6906d 100644 --- a/apps/client/src/services/attributes.spec.ts +++ b/apps/client/src/services/attributes.spec.ts @@ -6,10 +6,8 @@ import froca from "./froca"; import server from "./server.js"; // Spy on server methods to track calls -// @ts-expect-error the generic typing is causing issues here -server.put = vi.fn(async (url: string, data?: T) => ({} as T)); -// @ts-expect-error the generic typing is causing issues here -server.remove = vi.fn(async (url: string) => ({} as T)); +server.put = vi.fn(async () => ({})) as typeof server.put; +server.remove = vi.fn(async () => ({})) as typeof server.remove; describe("Set boolean with inheritance", () => { beforeEach(() => { diff --git a/apps/client/src/services/branches.ts b/apps/client/src/services/branches.ts index 8f31060242..15d24a10d7 100644 --- a/apps/client/src/services/branches.ts +++ b/apps/client/src/services/branches.ts @@ -120,7 +120,7 @@ async function deleteNotes(branchIdsToDelete: string[], forceDeleteAllClones = f if (moveToParent) { try { - await activateParentNotePath(); + await activateParentNotePath(branchIdsToDelete); } catch (e) { console.error(e); } @@ -152,13 +152,28 @@ async function deleteNotes(branchIdsToDelete: string[], forceDeleteAllClones = f return true; } -async function activateParentNotePath() { - // this is not perfect, maybe we should find the next/previous sibling, but that's more complex +async function activateParentNotePath(branchIdsToDelete: string[]) { const activeContext = appContext.tabManager.getActiveContext(); - const parentNotePathArr = activeContext?.notePathArray.slice(0, -1); + const activeNotePath = activeContext?.notePathArray ?? []; - if (parentNotePathArr && parentNotePathArr.length > 0) { - activeContext?.setNote(parentNotePathArr.join("/")); + // Find the deleted branch that appears earliest in the active note's path + let earliestIndex = activeNotePath.length; + for (const branchId of branchIdsToDelete) { + const branch = froca.getBranch(branchId); + if (branch) { + const index = activeNotePath.indexOf(branch.noteId); + if (index !== -1 && index < earliestIndex) { + earliestIndex = index; + } + } + } + + // Navigate to the parent of the highest deleted ancestor + if (earliestIndex < activeNotePath.length) { + const parentPath = activeNotePath.slice(0, earliestIndex); + if (parentPath.length > 0) { + await activeContext?.setNote(parentPath.join("/")); + } } } diff --git a/apps/client/src/services/bundle.ts b/apps/client/src/services/bundle.ts index 7cee01812b..fdee38ba34 100644 --- a/apps/client/src/services/bundle.ts +++ b/apps/client/src/services/bundle.ts @@ -26,7 +26,7 @@ type WithNoteId = T & { }; export type Widget = WithNoteId<(LegacyWidget | WidgetDefinitionWithType)>; -async function getAndExecuteBundle(noteId: string, originEntity = null, script = null, params = null) { +async function getAndExecuteBundle(noteId: string, originEntity: Entity | null = null, script: string | null = null, params: string | null = null) { const bundle = await server.post(`script/bundle/${noteId}`, { script, params diff --git a/apps/client/src/services/clipboard_ext.ts b/apps/client/src/services/clipboard_ext.ts index 9ab98af68f..16eea4ca49 100644 --- a/apps/client/src/services/clipboard_ext.ts +++ b/apps/client/src/services/clipboard_ext.ts @@ -1,3 +1,6 @@ +import { t } from "./i18n.js"; +import toast from "./toast.js"; + export function copyText(text: string) { if (!text) { return; @@ -6,29 +9,26 @@ export function copyText(text: string) { if (navigator.clipboard) { navigator.clipboard.writeText(text); return true; - } else { - // Fallback method: https://stackoverflow.com/a/72239825 - const textArea = document.createElement("textarea"); - textArea.value = text; - try { - document.body.appendChild(textArea); - textArea.focus(); - textArea.select(); - return document.execCommand('copy'); - } finally { - document.body.removeChild(textArea); - } + } + // Fallback method: https://stackoverflow.com/a/72239825 + const textArea = document.createElement("textarea"); + textArea.value = text; + try { + document.body.appendChild(textArea); + textArea.focus(); + textArea.select(); + return document.execCommand('copy'); + } finally { + document.body.removeChild(textArea); } + } catch (e) { console.warn(e); return false; } } -export async function copyTextWithToast(text: string) { - const t = (await import("./i18n.js")).t; - const toast = (await import("./toast.js")).default; - +export function copyTextWithToast(text: string) { if (copyText(text)) { toast.showMessage(t("clipboard.copy_success")); } else { diff --git a/apps/client/src/services/dialog.ts b/apps/client/src/services/dialog.ts index 8711ec1751..6888870fc9 100644 --- a/apps/client/src/services/dialog.ts +++ b/apps/client/src/services/dialog.ts @@ -1,9 +1,11 @@ import { Modal } from "bootstrap"; + import appContext from "../components/app_context.js"; import type { ConfirmDialogOptions, ConfirmDialogResult, ConfirmWithMessageOptions, MessageType } from "../widgets/dialogs/confirm.js"; +import { InfoExtraProps } from "../widgets/dialogs/info.jsx"; import type { PromptDialogOptions } from "../widgets/dialogs/prompt.js"; import { focusSavedElement, saveFocusedElement } from "./focus.js"; -import { InfoExtraProps } from "../widgets/dialogs/info.jsx"; +import keyboardActionsService from "./keyboard_actions.js"; export async function openDialog($dialog: JQuery, closeActDialog = true, config?: Partial) { if (closeActDialog) { @@ -25,7 +27,6 @@ export async function openDialog($dialog: JQuery, closeActDialog = } }); - const keyboardActionsService = (await import("./keyboard_actions.js")).default; keyboardActionsService.updateDisplayedShortcuts($dialog); return $dialog; diff --git a/apps/client/src/services/froca_updater.ts b/apps/client/src/services/froca_updater.ts index ca6c792746..8be1eceada 100644 --- a/apps/client/src/services/froca_updater.ts +++ b/apps/client/src/services/froca_updater.ts @@ -1,14 +1,16 @@ -import LoadResults from "./load_results.js"; -import froca from "./froca.js"; -import utils from "./utils.js"; -import options from "./options.js"; -import noteAttributeCache from "./note_attribute_cache.js"; -import FBranch, { type FBranchRow } from "../entities/fbranch.js"; -import FAttribute, { type FAttributeRow } from "../entities/fattribute.js"; +import type { OptionNames } from "@triliumnext/commons"; + +import appContext from "../components/app_context.js"; import FAttachment, { type FAttachmentRow } from "../entities/fattachment.js"; +import FAttribute, { type FAttributeRow } from "../entities/fattribute.js"; +import FBranch, { type FBranchRow } from "../entities/fbranch.js"; import type { default as FNote, FNoteRow } from "../entities/fnote.js"; import type { EntityChange } from "../server_types.js"; -import type { OptionNames } from "@triliumnext/commons"; +import froca from "./froca.js"; +import LoadResults from "./load_results.js"; +import noteAttributeCache from "./note_attribute_cache.js"; +import options from "./options.js"; +import utils from "./utils.js"; async function processEntityChanges(entityChanges: EntityChange[]) { const loadResults = new LoadResults(entityChanges); @@ -63,7 +65,7 @@ async function processEntityChanges(entityChanges: EntityChange[]) { if (entityName === "branches" && !((entity as FBranchRow).parentNoteId in froca.notes)) { missingNoteIds.push((entity as FBranchRow).parentNoteId); } else if (entityName === "attributes") { - let attributeEntity = entity as FAttributeRow; + const attributeEntity = entity as FAttributeRow; if (attributeEntity.type === "relation" && (attributeEntity.name === "template" || attributeEntity.name === "inherit") && !(attributeEntity.value in froca.notes)) { missingNoteIds.push(attributeEntity.value); } @@ -79,7 +81,6 @@ async function processEntityChanges(entityChanges: EntityChange[]) { noteAttributeCache.invalidate(); } - const appContext = (await import("../components/app_context.js")).default; await appContext.triggerEvent("entitiesReloaded", { loadResults }); } } diff --git a/apps/client/src/services/frontend_script_api_preact.ts b/apps/client/src/services/frontend_script_api_preact.ts index 2829ca101e..9ce7a52e72 100644 --- a/apps/client/src/services/frontend_script_api_preact.ts +++ b/apps/client/src/services/frontend_script_api_preact.ts @@ -1,4 +1,4 @@ -import { Fragment, h, VNode } from "preact"; +import { createContext, Fragment, h, VNode } from "preact"; import * as hooks from "preact/hooks"; import ActionButton from "../widgets/react/ActionButton"; @@ -47,6 +47,7 @@ export const preactAPI = Object.freeze({ // Core h, Fragment, + createContext, /** * Method that must be run for widget scripts that run on Preact, using JSX. The method just returns the same definition, reserved for future typechecking and perhaps validation purposes. diff --git a/apps/client/src/services/i18n.ts b/apps/client/src/services/i18n.ts index 5b5f38b762..0743596731 100644 --- a/apps/client/src/services/i18n.ts +++ b/apps/client/src/services/i18n.ts @@ -1,21 +1,14 @@ -import options from "./options.js"; +import { LOCALE_IDS, LOCALES, setDayjsLocale } from "@triliumnext/commons"; import i18next from "i18next"; import i18nextHttpBackend from "i18next-http-backend"; -import server from "./server.js"; -import { LOCALE_IDS, setDayjsLocale, type Locale } from "@triliumnext/commons"; import { initReactI18next } from "react-i18next"; -let locales: Locale[] | null; - /** * A deferred promise that resolves when translations are initialized. */ -export let translationsInitializedPromise = $.Deferred(); +export const translationsInitializedPromise = $.Deferred(); -export async function initLocale() { - const locale = ((options.get("locale") as string) || "en") as LOCALE_IDS; - - locales = await server.get("options/locales"); +export async function initLocale(locale: LOCALE_IDS = "en") { i18next.use(initReactI18next); await i18next.use(i18nextHttpBackend).init({ @@ -32,11 +25,7 @@ export async function initLocale() { } export function getAvailableLocales() { - if (!locales) { - throw new Error("Tried to load list of locales, but localization is not yet initialized.") - } - - return locales; + return LOCALES; } /** @@ -47,7 +36,7 @@ export function getAvailableLocales() { */ export function getLocaleById(localeId: string | null | undefined) { if (!localeId) return null; - return locales?.find((l) => l.id === localeId) ?? null; + return LOCALES.find((l) => l.id === localeId) ?? null; } export const t = i18next.t; diff --git a/apps/client/src/services/llm_chat.ts b/apps/client/src/services/llm_chat.ts index fa0a0279d3..cd6ab3e63f 100644 --- a/apps/client/src/services/llm_chat.ts +++ b/apps/client/src/services/llm_chat.ts @@ -27,7 +27,8 @@ export interface StreamCallbacks { export async function streamChatCompletion( messages: LlmMessage[], config: LlmChatConfig, - callbacks: StreamCallbacks + callbacks: StreamCallbacks, + abortSignal?: AbortSignal ): Promise { const headers = await server.getHeaders(); @@ -37,7 +38,8 @@ export async function streamChatCompletion( ...headers, "Content-Type": "application/json" } as HeadersInit, - body: JSON.stringify({ messages, config }) + body: JSON.stringify({ messages, config }), + signal: abortSignal }); if (!response.ok) { diff --git a/apps/client/src/services/note_autocomplete.ts b/apps/client/src/services/note_autocomplete.ts index 9ca4fa86fb..18982307ac 100644 --- a/apps/client/src/services/note_autocomplete.ts +++ b/apps/client/src/services/note_autocomplete.ts @@ -68,7 +68,8 @@ async function autocompleteSourceForCKEditor(queryText: string) { name: row.notePathTitle || "", link: `#${row.notePath}`, notePath: row.notePath, - highlightedNotePathTitle: row.highlightedNotePathTitle + highlightedNotePathTitle: row.highlightedNotePathTitle, + icon: row.icon }; }) ); diff --git a/apps/client/src/services/render.tsx b/apps/client/src/services/render.tsx index 682efa8871..31450b3a82 100644 --- a/apps/client/src/services/render.tsx +++ b/apps/client/src/services/render.tsx @@ -18,6 +18,10 @@ async function render(note: FNote, $el: JQuery, onError?: ErrorHand for (const renderNoteId of renderNoteIds) { const bundle = await server.postWithSilentInternalServerError(`script/bundle/${renderNoteId}`); + if (!bundle) { + throw new Error(`Script note '${renderNoteId}' could not be loaded. It may be protected and require an active protected session.`); + } + const $scriptContainer = $("
"); $el.append($scriptContainer); diff --git a/apps/client/src/services/server.ts b/apps/client/src/services/server.ts index 010b57cae1..2d9d8273ae 100644 --- a/apps/client/src/services/server.ts +++ b/apps/client/src/services/server.ts @@ -1,3 +1,4 @@ +import { t } from "./i18n.js"; import utils, { isShare } from "./utils.js"; import ValidationError from "./validation_error.js"; @@ -32,8 +33,7 @@ async function getHeaders(headers?: Headers) { return {}; } - const appContext = (await import("../components/app_context.js")).default; - const activeNoteContext = appContext.tabManager ? appContext.tabManager.getActiveContext() : null; + const activeNoteContext = glob.appContext?.tabManager ? glob.appContext.tabManager.getActiveContext() : null; // headers need to be lowercase because node.js automatically converts them to lower case // also avoiding using underscores instead of dashes since nginx filters them out by default @@ -344,6 +344,7 @@ async function reportError(method: string, url: string, statusCode: number, resp } catch (e) {} } + // Dynamic import to avoid circular dependency (toast → app_context → options → server). const toastService = (await import("./toast.js")).default; const messageStr = (typeof message === "string" ? message : JSON.stringify(message)) || "-"; @@ -357,7 +358,6 @@ async function reportError(method: string, url: string, statusCode: number, resp ...response }); } else { - const { t } = await import("./i18n.js"); if (statusCode === 400 && (url.includes("%23") || url.includes("%2F"))) { toastService.showPersistent({ id: "trafik-blocked", @@ -371,8 +371,7 @@ async function reportError(method: string, url: string, statusCode: number, resp t("server.unknown_http_error_content", { statusCode, method, url, message: messageStr }), 15_000); } - const { logError } = await import("./ws.js"); - logError(`${statusCode} ${method} ${url} - ${message}`); + window.logError(`${statusCode} ${method} ${url} - ${message}`); } } diff --git a/apps/client/src/services/spaced_update.spec.ts b/apps/client/src/services/spaced_update.spec.ts new file mode 100644 index 0000000000..ab649f3435 --- /dev/null +++ b/apps/client/src/services/spaced_update.spec.ts @@ -0,0 +1,87 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; + +import SpacedUpdate from "./spaced_update"; + +// Mock logError which is a global in Trilium +vi.stubGlobal("logError", vi.fn()); + +describe("SpacedUpdate", () => { + beforeEach(() => { + vi.useFakeTimers(); + }); + + afterEach(() => { + vi.useRealTimers(); + }); + + it("should only call updater once per interval even with multiple pending callbacks", async () => { + const updater = vi.fn(async () => { + // Simulate a slow network request - this is where the race condition occurs + await new Promise((resolve) => setTimeout(resolve, 100)); + }); + + const spacedUpdate = new SpacedUpdate(updater, 50); + + // Simulate rapid typing - each keystroke calls scheduleUpdate() + // This queues multiple setTimeout callbacks due to recursive scheduleUpdate() calls + for (let i = 0; i < 10; i++) { + spacedUpdate.scheduleUpdate(); + // Small delay between keystrokes + await vi.advanceTimersByTimeAsync(5); + } + + // Advance time past the update interval to trigger the update + await vi.advanceTimersByTimeAsync(100); + + // Let the "network request" complete and any pending callbacks run + await vi.advanceTimersByTimeAsync(200); + + // The updater should have been called only ONCE, not multiple times + // With the bug, multiple pending setTimeout callbacks would all pass the time check + // during the async updater call and trigger multiple concurrent requests + expect(updater).toHaveBeenCalledTimes(1); + }); + + it("should call updater again if changes occur during the update", async () => { + const updater = vi.fn(async () => { + await new Promise((resolve) => setTimeout(resolve, 50)); + }); + + const spacedUpdate = new SpacedUpdate(updater, 30); + + // First update + spacedUpdate.scheduleUpdate(); + await vi.advanceTimersByTimeAsync(40); + + // Schedule another update while the first one is in progress + spacedUpdate.scheduleUpdate(); + + // Let first update complete + await vi.advanceTimersByTimeAsync(60); + + // Advance past the interval again for the second update + await vi.advanceTimersByTimeAsync(100); + + // Should have been called twice - once for each distinct change period + expect(updater).toHaveBeenCalledTimes(2); + }); + + it("should restore changed flag on error so retry can happen", async () => { + const updater = vi.fn() + .mockRejectedValueOnce(new Error("Network error")) + .mockResolvedValue(undefined); + + const spacedUpdate = new SpacedUpdate(updater, 50); + + spacedUpdate.scheduleUpdate(); + + // Advance to trigger first update (which will fail) + await vi.advanceTimersByTimeAsync(60); + + // The error should have restored the changed flag, so scheduling again should work + spacedUpdate.scheduleUpdate(); + await vi.advanceTimersByTimeAsync(60); + + expect(updater).toHaveBeenCalledTimes(2); + }); +}); diff --git a/apps/client/src/services/spaced_update.ts b/apps/client/src/services/spaced_update.ts index 3804c4949b..13cdbd7b5e 100644 --- a/apps/client/src/services/spaced_update.ts +++ b/apps/client/src/services/spaced_update.ts @@ -77,16 +77,22 @@ export default class SpacedUpdate { } if (Date.now() - this.lastUpdated > this.updateInterval) { + // Update these BEFORE the async call to prevent race conditions. + // Multiple setTimeout callbacks may be pending from recursive scheduleUpdate() calls. + // Without this, they would all pass the time check during the await and trigger multiple requests. + this.lastUpdated = Date.now(); + this.changed = false; + this.onStateChanged("saving"); try { await this.updater(); this.onStateChanged("saved"); - this.changed = false; } catch (e) { + // Restore changed flag on error so a retry can happen + this.changed = true; this.onStateChanged("error"); logError(getErrorMessage(e)); } - this.lastUpdated = Date.now(); } else { // update isn't triggered but changes are still pending, so we need to schedule another check this.scheduleUpdate(); diff --git a/apps/client/src/services/syntax_highlight.ts b/apps/client/src/services/syntax_highlight.ts index 3b2c35f682..1aa9084ce4 100644 --- a/apps/client/src/services/syntax_highlight.ts +++ b/apps/client/src/services/syntax_highlight.ts @@ -33,6 +33,14 @@ export async function formatCodeBlocks($container: JQuery) { applySingleBlockSyntaxHighlight($(codeBlock), normalizedMimeType); } } + + // Add click-to-copy for inline code (code elements not inside pre) + if (glob.device !== "print") { + const inlineCodeElements = $container.find("code:not(pre code)"); + for (const inlineCode of inlineCodeElements) { + applyInlineCodeCopy($(inlineCode)); + } + } } export function applyCopyToClipboardButton($codeBlock: JQuery) { @@ -51,6 +59,23 @@ export function applyCopyToClipboardButton($codeBlock: JQuery) { $codeBlock.parent().append($copyButton); } +export function applyInlineCodeCopy($inlineCode: JQuery) { + $inlineCode + .addClass("copyable-inline-code") + .attr("title", t("code_block.click_to_copy")) + .off("click") + .on("click", (e) => { + e.stopPropagation(); + + const text = $inlineCode.text(); + if (!isShare) { + copyTextWithToast(text); + } else { + copyText(text); + } + }); +} + /** * Applies syntax highlight to the given code block (assumed to be
), using highlight.js.
  */
diff --git a/apps/client/src/services/theme.ts b/apps/client/src/services/theme.ts
new file mode 100644
index 0000000000..9aa42c22ba
--- /dev/null
+++ b/apps/client/src/services/theme.ts
@@ -0,0 +1,35 @@
+export function getThemeStyle(): "auto" | "light" | "dark" {
+    const configuredTheme = window.glob?.theme;
+    if (configuredTheme === "auto" || configuredTheme === "next") {
+        return "auto";
+    }
+
+    if (configuredTheme === "light" || configuredTheme === "dark") {
+        return configuredTheme;
+    }
+
+    if (configuredTheme === "next-light") {
+        return "light";
+    }
+
+    if (configuredTheme === "next-dark") {
+        return "dark";
+    }
+
+    const style = window.getComputedStyle(document.body);
+    const themeStyle = style.getPropertyValue("--theme-style");
+    if (style.getPropertyValue("--theme-style-auto") !== "true" && (themeStyle === "light" || themeStyle === "dark")) {
+        return themeStyle as "light" | "dark";
+    }
+
+    return "auto";
+}
+
+export function getEffectiveThemeStyle(): "light" | "dark" {
+    const themeStyle = getThemeStyle();
+    if (themeStyle === "auto") {
+        return window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
+    }
+
+    return themeStyle === "dark" ? "dark" : "light";
+}
diff --git a/apps/client/src/services/utils.ts b/apps/client/src/services/utils.ts
index 30b5e4eaf7..67bbdd0e26 100644
--- a/apps/client/src/services/utils.ts
+++ b/apps/client/src/services/utils.ts
@@ -455,9 +455,7 @@ export function openInAppHelpFromUrl(inAppHelpPage: string) {
 export async function openInReusableSplit(targetNoteId: string, targetViewMode: ViewMode, openOpts: {
     hoistedNoteId?: string;
 } = {}) {
-    // Dynamic import to avoid import issues in tests.
-    const appContext = (await import("../components/app_context.js")).default;
-    const activeContext = appContext.tabManager.getActiveContext();
+    const activeContext = glob.appContext?.tabManager?.getActiveContext();
     if (!activeContext) {
         return;
     }
@@ -467,7 +465,7 @@ export async function openInReusableSplit(targetNoteId: string, targetViewMode:
     if (!existingSubcontext) {
         // The target split is not already open, open a new split with it.
         const { ntxId } = subContexts[subContexts.length - 1];
-        appContext.triggerCommand("openNewNoteSplit", {
+        glob.appContext?.triggerCommand("openNewNoteSplit", {
             ntxId,
             notePath: targetNoteId,
             hoistedNoteId: openOpts.hoistedNoteId,
diff --git a/apps/client/src/services/ws.ts b/apps/client/src/services/ws.ts
index 1002abe9f7..b8c606d43b 100644
--- a/apps/client/src/services/ws.ts
+++ b/apps/client/src/services/ws.ts
@@ -1,13 +1,15 @@
-import utils from "./utils.js";
-import toastService from "./toast.js";
-import server from "./server.js";
-import options from "./options.js";
-import frocaUpdater from "./froca_updater.js";
-import appContext from "../components/app_context.js";
-import { t } from "./i18n.js";
-import type { EntityChange } from "../server_types.js";
 import { WebSocketMessage } from "@triliumnext/commons";
+
+import appContext from "../components/app_context.js";
+import type { EntityChange } from "../server_types.js";
+import bundleService from "./bundle.js";
+import froca from "./froca.js";
+import frocaUpdater from "./froca_updater.js";
+import { t } from "./i18n.js";
+import options from "./options.js";
+import server from "./server.js";
 import toast from "./toast.js";
+import utils from "./utils.js";
 
 type MessageHandler = (message: WebSocketMessage) => void;
 let messageHandlers: MessageHandler[] = [];
@@ -126,20 +128,14 @@ async function handleMessage(event: MessageEvent) {
     } else if (message.type === "frontend-update") {
         await executeFrontendUpdate(message.data.entityChanges);
     } else if (message.type === "sync-hash-check-failed") {
-        toastService.showError(t("ws.sync-check-failed"), 60000);
+        toast.showError(t("ws.sync-check-failed"), 60000);
     } else if (message.type === "consistency-checks-failed") {
-        toastService.showError(t("ws.consistency-checks-failed"), 50 * 60000);
+        toast.showError(t("ws.consistency-checks-failed"), 50 * 60000);
     } else if (message.type === "api-log-messages") {
         appContext.triggerEvent("apiLogMessages", { noteId: message.noteId, messages: message.messages });
     } else if (message.type === "toast") {
-        toastService.showMessage(message.message);
+        toast.showMessage(message.message, message.timeout);
     } else if (message.type === "execute-script") {
-        // TODO: Remove after porting the file
-        // @ts-ignore
-        const bundleService = (await import("./bundle.js")).default as any;
-        // TODO: Remove after porting the file
-        // @ts-ignore
-        const froca = (await import("./froca.js")).default as any;
         const originEntity = message.originEntityId ? await froca.getNote(message.originEntityId) : null;
 
         bundleService.getAndExecuteBundle(message.currentNoteId, originEntity, message.script, message.params);
@@ -161,7 +157,7 @@ function waitForEntityChangeId(desiredEntityChangeId: number) {
 
     return new Promise((res, rej) => {
         entityChangeIdReachedListeners.push({
-            desiredEntityChangeId: desiredEntityChangeId,
+            desiredEntityChangeId,
             resolvePromise: res,
             start: Date.now()
         });
@@ -205,7 +201,7 @@ async function consumeFrontendUpdateData() {
             } else {
                 console.log("nonProcessedEntityChanges causing the timeout", nonProcessedEntityChanges);
 
-                toastService.showError(t("ws.encountered-error", { message: e.message }));
+                toast.showError(t("ws.encountered-error", { message: e.message }));
             }
         }
 
diff --git a/apps/client/src/setup.ts b/apps/client/src/setup.ts
index 30232b85a3..67ad3e835d 100644
--- a/apps/client/src/setup.ts
+++ b/apps/client/src/setup.ts
@@ -99,7 +99,7 @@ class SetupController {
     }
 
     private async finish() {
-        const syncServerHost = this.syncServerHostInput.value.trim();
+        const syncServerHost = this.syncServerHostInput.value.trim().replace(/\/+$/, "");
         const syncProxy = this.syncProxyInput.value.trim();
         const password = this.passwordInput.value;
 
diff --git a/apps/client/src/stylesheets/style.css b/apps/client/src/stylesheets/style.css
index 536db2d9b5..baff2d14dc 100644
--- a/apps/client/src/stylesheets/style.css
+++ b/apps/client/src/stylesheets/style.css
@@ -1230,6 +1230,43 @@ a.external:not(.no-arrow):after, a[href^="http://"]:not(.no-arrow):after, a[href
     width: 100%;
 }
 
+/* Expandable include note styles */
+.include-note-title-row {
+    display: flex;
+    align-items: center;
+    gap: 5px;
+    cursor: pointer;
+}
+
+.include-note-title-row .include-note-title {
+    margin: 0;
+}
+
+.include-note-toggle {
+    background: none;
+    border: none;
+    padding: 2px;
+    cursor: pointer;
+    font-size: 1.2em;
+    color: var(--main-text-color);
+    transition: transform 0.2s ease;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+.include-note-toggle:hover {
+    color: var(--main-link-color);
+}
+
+.include-note-toggle.expanded {
+    transform: rotate(90deg);
+}
+
+.include-note[data-box-size="expandable"] .include-note-content {
+    margin-top: 10px;
+}
+
 .alert {
     padding: 8px 14px;
     width: auto;
diff --git a/apps/client/src/stylesheets/theme-next.css b/apps/client/src/stylesheets/theme-next.css
deleted file mode 100644
index 1c8a7d810d..0000000000
--- a/apps/client/src/stylesheets/theme-next.css
+++ /dev/null
@@ -1,11 +0,0 @@
-/* Import the light color scheme.
- * This is the base color scheme, always active and overridden by the dark
- * color scheme stylesheet when necessary. */
-@import url(./theme-next-light.css);
-
-/* Import the dark color scheme when the system preference is set to dark mode */
-@import url(./theme-next-dark.css) (prefers-color-scheme: dark);
-
-:root {
-    --theme-style-auto: true;
-}
diff --git a/apps/client/src/stylesheets/theme.css b/apps/client/src/stylesheets/theme.css
deleted file mode 100644
index e99702d325..0000000000
--- a/apps/client/src/stylesheets/theme.css
+++ /dev/null
@@ -1,11 +0,0 @@
-/* Import the light color scheme.
- * This is the base color scheme, always active and overridden by the dark
- * color scheme stylesheet when necessary. */
-@import url(./theme-light.css);
-
-/* Import the dark color scheme when the system preference is set to dark mode */
-@import url(./theme-dark.css) (prefers-color-scheme: dark);
-
-:root {
-    --theme-style-auto: true;
-}
diff --git a/apps/client/src/translations/ar/translation.json b/apps/client/src/translations/ar/translation.json
index 70c3c2f737..d2c9d7a44d 100644
--- a/apps/client/src/translations/ar/translation.json
+++ b/apps/client/src/translations/ar/translation.json
@@ -393,9 +393,7 @@
   },
   "delete_notes": {
     "close": "غلق",
-    "cancel": "الغاء",
-    "ok": "نعم",
-    "delete_notes_preview": "حذف معاينة الملاحظات"
+    "cancel": "الغاء"
   },
   "export": {
     "close": "غلق",
@@ -626,7 +624,8 @@
     "date-and-time": "التاريخ والوقت",
     "no_backup_yet": "لايوجد نسخة احتياطية لحد الان",
     "enable_daily_backup": "تمكين النسخ الاحتياطي اليومي",
-    "backup_database_now": "نسخ اختياطي لقاعدة البيانات الان"
+    "backup_database_now": "نسخ اختياطي لقاعدة البيانات الان",
+    "download": "تنزيل"
   },
   "etapi": {
     "created": "تم الأنشاء",
@@ -663,7 +662,6 @@
     "default_shortcuts": "اختصارات افتراضية"
   },
   "sync_2": {
-    "timeout_unit": "ميلي ثانية",
     "note": "ملاحظة",
     "save": "حفظ",
     "help": "المساعدة",
@@ -1129,9 +1127,7 @@
   "spellcheck": {
     "title": "التدقيق الاملائي",
     "enable": "تفعيل التدقيق الاملائي",
-    "language_code_label": "رمز اللغة او رموز اللغات",
-    "available_language_codes_label": "رموز اللغات المتاحة:",
-    "language_code_placeholder": "على سبيل المثال \"en-US\", \"de-AI\""
+    "language_code_label": "رمز اللغة او رموز اللغات"
   },
   "note-map": {
     "button-link-map": "خريطة الروابط",
diff --git a/apps/client/src/translations/ca/translation.json b/apps/client/src/translations/ca/translation.json
index 32de8b1615..d4cbd59d2d 100644
--- a/apps/client/src/translations/ca/translation.json
+++ b/apps/client/src/translations/ca/translation.json
@@ -25,8 +25,7 @@
   },
   "delete_notes": {
     "close": "Tanca",
-    "cancel": "Cancel·la",
-    "ok": "OK"
+    "cancel": "Cancel·la"
   },
   "export": {
     "close": "Tanca",
diff --git a/apps/client/src/translations/cn/translation.json b/apps/client/src/translations/cn/translation.json
index 5b57b0b279..6d2b66ebd3 100644
--- a/apps/client/src/translations/cn/translation.json
+++ b/apps/client/src/translations/cn/translation.json
@@ -88,7 +88,6 @@
     "also_delete_note": "同时删除笔记"
   },
   "delete_notes": {
-    "delete_notes_preview": "删除笔记预览",
     "close": "关闭",
     "delete_all_clones_description": "同时删除所有克隆(可以在最近修改中撤消)",
     "erase_notes_description": "通常(软)删除仅标记笔记为已删除,可以在一段时间内通过最近修改对话框撤消。选中此选项将立即擦除笔记,不可撤销。",
@@ -96,9 +95,7 @@
     "notes_to_be_deleted": "将删除以下笔记 ({{notesCount}})",
     "no_note_to_delete": "没有笔记将被删除(仅克隆)。",
     "broken_relations_to_be_deleted": "将删除以下关系并断开连接 ({{ relationCount}})",
-    "cancel": "取消",
-    "ok": "确定",
-    "deleted_relation_text": "笔记 {{- note}} (将被删除的笔记) 被以下关系 {{- relation}} 引用, 来自 {{- source}}。"
+    "cancel": "取消"
   },
   "export": {
     "export_note_title": "导出笔记",
@@ -368,7 +365,7 @@
     "calendar_root": "标记应用作为每日笔记的根。只应标记一个笔记。",
     "archived": "含有此标签的笔记默认在搜索结果中不可见(也适用于跳转到、添加链接对话框等)。",
     "exclude_from_export": "笔记(及其子树)不会包含在任何笔记导出中",
-    "run": "定义脚本应运行的事件。可能的值包括:\n
    \n
  • frontendStartup - Trilium前端启动时(或刷新时),但不会在移动端执行。
  • \n
  • mobileStartup - Trilium前端启动时(或刷新时), 在移动端会执行。
  • \n
  • backendStartup - Trilium后端启动时
  • \n
  • hourly - 每小时运行一次。您可以使用附加标签runAtHour指定小时。
  • \n
  • daily - 每天运行一次
  • \n
", + "run": "定义脚本应运行的事件。可能的值包括:\n
    \n
  • frontendStartup - Trilium前端启动时(或刷新时),但不会在移动端执行。
  • \n
  • mobileStartup - Trilium前端启动时(或刷新时), 在移动端会执行。
  • \n
  • backendStartup - Trilium后端启动时。
  • \n
  • hourly - 每小时运行一次。您可以使用附加标签runAtHour指定小时。
  • \n
  • daily - 每天运行一次。
  • \n
", "run_on_instance": "定义应在哪个Trilium实例上运行。默认为所有实例。", "run_at_hour": "应在哪个小时运行。应与#run=hourly一起使用。可以多次定义,以便一天内运行多次。", "disable_inclusion": "含有此标签的脚本不会包含在父脚本执行中。", @@ -804,7 +801,10 @@ "expand_first_level": "展开直接子代", "expand_nth_level": "展开 {{depth}} 层", "expand_all_levels": "展开所有层级", - "hide_child_notes": "隐藏树中的子笔记" + "hide_child_notes": "隐藏树中的子笔记", + "open_all_in_tabs": "全部打开", + "open_all_in_tabs_tooltip": "在新标签页中打开所有结果", + "open_all_confirm": "这将在新标签页中打开 {{count}} 个笔记。继续吗?" }, "edited_notes": { "no_edited_notes_found": "今天还没有编辑过的笔记...", @@ -858,7 +858,8 @@ "collapse": "折叠到正常大小", "title": "笔记地图", "fix-nodes": "固定节点", - "link-distance": "链接距离" + "link-distance": "链接距离", + "too-many-notes": "此子树包含 {{count}} 个笔记,超过了笔记地图中可显示的 {{max}} 个笔记的限制。" }, "note_paths": { "title": "笔记路径", @@ -1063,7 +1064,8 @@ "note_already_in_diagram": "笔记 \"{{title}}\" 已经在图中。", "enter_title_of_new_note": "输入新笔记的标题", "default_new_note_title": "新笔记", - "click_on_canvas_to_place_new_note": "点击画布以放置新笔记" + "click_on_canvas_to_place_new_note": "点击画布以放置新笔记", + "rename_relation": "重命名关系" }, "backend_log": { "refresh": "刷新" @@ -1337,7 +1339,8 @@ "date-and-time": "日期和时间", "path": "路径", "database_backed_up_to": "数据库已备份到 {{backupFilePath}}", - "no_backup_yet": "尚无备份" + "no_backup_yet": "尚无备份", + "download": "下载" }, "etapi": { "title": "ETAPI", @@ -1435,12 +1438,15 @@ "spellcheck": { "title": "拼写检查", "description": "这些选项仅适用于桌面版本,浏览器将使用其原生的拼写检查功能。", - "enable": "启用拼写检查", - "language_code_label": "语言代码", - "language_code_placeholder": "例如 \"en-US\", \"de-AT\"", - "multiple_languages_info": "多种语言可以用逗号分隔,例如 \"en-US, de-DE, cs\"。 ", - "available_language_codes_label": "可用的语言代码:", - "restart-required": "拼写检查选项的更改将在应用重启后生效。" + "enable": "拼写检查", + "language_code_label": "拼写检查语言", + "restart-required": "拼写检查选项的更改将在应用重启后生效。", + "custom_dictionary_title": "自定义词典", + "custom_dictionary_description": "添加到词典中的单词会在您的所有设备上同步。", + "custom_dictionary_edit": "自定义词", + "custom_dictionary_edit_description": "编辑拼写检查器不应标记的单词列表。更改将在重启后生效。", + "custom_dictionary_open": "编辑词典", + "related_description": "配置拼写检查语言和自定义词典。" }, "sync_2": { "config_title": "同步配置", @@ -1456,7 +1462,7 @@ "test_description": "测试和同步服务器之间的连接。如果同步服务器没有初始化,会将本地文档同步到同步服务器上。", "test_button": "测试同步", "handshake_failed": "同步服务器握手失败,错误:{{message}}", - "timeout_unit": "毫秒" + "timeout_description": "同步连接速度慢时,应该等待多久才放弃?如果网络不稳定,请增加等待时间。" }, "api_log": { "close": "关闭" @@ -1879,7 +1885,7 @@ }, "content_language": { "title": "内容语言", - "description": "选择一种或多种语言出现在只读或可编辑文本注释的基本属性,这将支持拼写检查或从右向左之类的功能。" + "description": "在只读或可编辑文本笔记的“基本属性”部分,选择一种或多种语言,这些语言将显示在语言选择列表中。这将启用拼写检查、从右到左的阅读支持和文本提取(OCR)等功能。" }, "switch_layout_button": { "title_vertical": "将编辑面板移至底部", @@ -2234,7 +2240,9 @@ "sample_xy": "散点图", "sample_venn": "韦恩图", "sample_ishikawa": "鱼骨图", - "placeholder": "输入你的美人鱼图的内容,或者使用下面的示例图之一。" + "placeholder": "输入你的美人鱼图的内容,或者使用下面的示例图之一。", + "sample_treeview": "树形视图", + "sample_wardley": "沃德利地图" }, "llm_chat": { "placeholder": "输入消息…", @@ -2265,7 +2273,8 @@ "note_context_disabled": "点击即可将当前注释添加到上下文中", "no_provider_message": "未配置人工智能提供商。添加一个即可开始对话。", "add_provider": "添加人工智能提供商", - "note_tools": "笔记访问" + "note_tools": "笔记访问", + "sources_summary": "来自 {{sites}} 个网站的 {{count}} 个来源" }, "sidebar_chat": { "title": "AI对话", @@ -2288,7 +2297,10 @@ "processing": "正在处理...", "processing_started": "OCR识别已开始。请稍候片刻并刷新页面。", "processing_failed": "OCR处理启动失败", - "view_extracted_text": "查看提取的文本(OCR)" + "view_extracted_text": "查看提取的文本(OCR)", + "processing_complete": "OCR识别处理完成。", + "text_filtered_low_confidence": "OCR 检测到文本,置信度为 {{confidence}}% ,但由于您的最小阈值为 {{threshold}}% ,因此该文本已被丢弃。", + "open_media_settings": "打开设置" }, "mind-map": { "addChild": "添加子节点", @@ -2306,6 +2318,13 @@ }, "llm": { "settings_description": "配置人工智能和大语言模型集成。", - "add_provider": "添加提供商" + "add_provider": "添加提供商", + "settings_title": "AI / LLM", + "feature_not_enabled": "在“设置”→“高级”→“实验性功能”中启用 LLM 实验性功能,即可使用 AI 集成。", + "add_provider_title": "添加AI供应商", + "configured_providers": "已配置的供应商", + "no_providers_configured": "尚未配置任何供应商。", + "provider_name": "名称", + "provider_type": "供应商" } } diff --git a/apps/client/src/translations/cs/translation.json b/apps/client/src/translations/cs/translation.json index b5cb420326..459a097d57 100644 --- a/apps/client/src/translations/cs/translation.json +++ b/apps/client/src/translations/cs/translation.json @@ -21,8 +21,17 @@ }, "bundle-error": { "title": "Načtení uživatelského skriptu selhalo", - "message": "Uživatelský skript z poznámky s ID \"{{id}}\" a názvem \"{{title}}\" nemohl být spuštěn z důvodu: \n\n{{message}}" - } + "message": "Skript nebylo možné spustit z následujícího důvodu:\n\n{{message}}" + }, + "widget-list-error": { + "title": "Nepodařilo se získat seznam widgetů ze serveru" + }, + "widget-render-error": { + "title": "Nepodařilo se vykreslit vlastní React widget" + }, + "widget-missing-parent": "Vlastní widget nemá definovanou povinnou vlastnost „{{property}}“.\n\nPokud má být tento skript spuštěn bez prvku uživatelského rozhraní, použijte místo toho „#run=frontendStartup“.", + "open-script-note": "Otevřít poznámku se skriptem", + "scripting-error": "Chyba vlastního skriptu: {{title}}" }, "add_link": { "add_link": "Přidat odkaz", @@ -68,16 +77,13 @@ }, "delete_notes": { "cancel": "Zrušit", - "ok": "OK", "close": "Zavřít", - "delete_notes_preview": "Odstranit náhled poznámek", "delete_all_clones_description": "Odstraňte také všechny klony (lze vrátit zpět v nedávných změnách)", "erase_notes_description": "Normální (měkké) smazání pouze označí poznámky jako smazané a lze je během určité doby obnovit (v dialogovém okně posledních změn). Zaškrtnutím této možnosti se poznámky okamžitě vymažou a nebude možné je obnovit.", "erase_notes_warning": "Trvale smažte poznámky (nelze vrátit zpět), včetně všech klonů. Tím se vynutí opětovné načtení aplikace.", "notes_to_be_deleted": "Následující poznámky budou smazány ({{notesCount}})", "no_note_to_delete": "Žádná poznámka nebude smazána (pouze klony).", - "broken_relations_to_be_deleted": "Následující vazby budou přerušeny a smazány ({{relationCount}})", - "deleted_relation_text": "Poznámka {{- note}} (bude smazána) je odkazována vazbou {{- relation}} pocházející z {{- source}}." + "broken_relations_to_be_deleted": "Následující vazby budou přerušeny a smazány ({{relationCount}})" }, "export": { "close": "Zavřít", @@ -111,8 +117,2261 @@ "note_cloned": "Poznámka „{{clonedTitle}}“ bylo naklonována do „{{targetTitle}}“" }, "zpetne_odkazy": { - "backlink_one": "{{count}} zpětný odkaz", - "backlink_few": "{{count}} zpětné odkazy", - "backlink_other": "{{count}} zpětných odkazů" + "backlink_one": "{{count}} Zpětný odkaz", + "backlink_few": "{{count}} Zpětné odkazy", + "backlink_other": "{{count}} Zpětných odkazů", + "relation": "vazba" + }, + "help": { + "title": "Rychlý přehled", + "editShortcuts": "Upravit klávesové zkratky", + "noteNavigation": "Navigace v poznámkách", + "goUpDown": "posunout nahoru/dolů v seznamu poznámek", + "collapseExpand": "sbalit/rozbalit uzel", + "notSet": "nenastaveno", + "goBackForwards": "jít zpět / vpřed v historii", + "showJumpToNoteDialog": "zobrazit dialog „Přejít na“", + "scrollToActiveNote": "posunout na aktivní poznámku", + "jumpToParentNote": "přejít na nadřazenou poznámku", + "collapseWholeTree": "sbalit celý strom poznámek", + "collapseSubTree": "sbalit podstrom", + "tabShortcuts": "Klávesové zkratky záložek", + "newTabNoteLink": "kliknutí na odkaz na poznámku otevře poznámku v nové záložce", + "newTabWithActivationNoteLink": "kliknutí na odkaz na poznámku otevře a aktivuje poznámku v nové záložce", + "onlyInDesktop": "Pouze na počítači (Electron build)", + "openEmptyTab": "otevřít prázdnou záložku", + "closeActiveTab": "zavřít aktivní záložku", + "activateNextTab": "aktivovat další záložku", + "activatePreviousTab": "aktivovat předchozí záložku", + "creatingNotes": "Vytváření poznámek", + "createNoteAfter": "vytvořit novou poznámku za aktivní poznámkou", + "createNoteInto": "vytvořit novou podpoznámku v aktivní poznámce", + "editBranchPrefix": "upravit předponu klonu aktivní poznámky", + "movingCloningNotes": "Přesouvání / klonování poznámtek", + "moveNoteUpDown": "přesunout poznámku nahoru/dolů v seznamu poznámek", + "moveNoteUpHierarchy": "přesunout poznámku výše v hierarchii", + "multiSelectNote": "vybrat více poznámek nad/pod", + "selectAllNotes": "vybrat všechny poznámky v aktuální úrovni", + "selectNote": "vybrat poznámku", + "copyNotes": "kopírovat aktivní poznámku (nebo aktuální výběr) do schránky (používá se pro klonování)", + "cutNotes": "vyříznout aktuální poznámky (nebo aktuální výběr) do schránky (používá se pro přesouvání poznámek)", + "pasteNotes": "vložit poznámku/poznámky jako podpoznámku do aktivní poznámky (což je buď přesun nebo klonování v závislosti na tom, zda byla do schránky zkopírována nebo vyříznuta)", + "deleteNotes": "smazat poznámku / podstrom", + "editingNotes": "Upravování poznámek", + "editNoteTitle": "V okně stromu přepne z okna stromu do názvu poznámky. Vstup z názvu poznámky přesune fokus do textového editoru. Ctrl+. přepne z editoru zpět do okna stromu.", + "createEditLink": "vytvořit / upravit externí odkaz", + "createInternalLink": "vytvořit interní odkaz", + "followLink": "sledovat odkaz pod kurzorem", + "insertDateTime": "vložit aktuální datum a čas na pozici kurzoru", + "jumpToTreePane": "přeskočit do okna stromu a posunout se k aktivní poznámce", + "markdownAutoformat": "Automatické formátování podobné ⟨Markdown⟩", + "headings": "##, ###, #### následované mezerou pro nadpisy", + "bulletList": "* nebo - následované mezerou pro odrážky", + "numberedList": "1. nebo 1) následované mezerou pro číslovaný seznam", + "blockQuote": "začněte řádek > následovaný mezerou pro blok citace", + "troubleshooting": "Řešení problémů", + "reloadFrontend": "znovu načíst ⟨Trilium⟩ ⟨frontend⟩", + "showDevTools": "zobrazit nástroje pro vývojáře", + "showSQLConsole": "zobrazit ⟨SQL⟩ konzoli", + "other": "Ostatní", + "quickSearch": "zaměřit se na rychlé vyhledávání", + "inPageSearch": "vyhledávání na stránce" + }, + "import": { + "importIntoNote": "Import do poznámky", + "chooseImportFile": "Vyberte soubor k importu", + "importDescription": "Obsah vybraných souborů bude importován jako dceřiné poznámky do", + "importZipRecommendation": "Při importu ZIP souboru bude hierarchie poznámek odrážet strukturu podadresářů v archivu.", + "options": "Nastavení", + "safeImportTooltip": "Exportované soubory Trilium .zip mohou obsahovat spustitelné skripty, které mohou mít škodlivé chování. Bezpečný import deaktivuje automatické spouštění všech importovaných skriptů. Zrušte zaškrtnutí \"Bezpečný import\" pouze v případě, že importovaný archiv má obsahovat spustitelné skripty a plně důvěřujete obsahu importovaného souboru.", + "safeImport": "Bezpečný import", + "explodeArchivesTooltip": "Pokud je toto zaškrtnuto, Trilium bude číst .zip, .enex a .opml soubory a vytvářet poznámky ze souborů uvnitř těchto archivů. Pokud není zaškrtnuto, Trilium připojí samotné archivy k poznámce.", + "explodeArchives": "Číst obsah archivů .zip, .enex a .opml.", + "shrinkImagesTooltip": "

Pokud zaškrtnete tuto možnost, Trilium se pokusí zmenšit importované obrázky škálováním a optimalizací, což může ovlivnit vnímanou kvalitu obrazu. Pokud není zaškrtnuto, obrázky budou importovány beze změn.

To se nevztahuje na importy .zip s metadaty, protože se předpokládá, že tyto soubory jsou již optimalizovány.

", + "shrinkImages": "Zmenšit obrázky", + "textImportedAsText": "Importovat HTML, Markdown a TXT jako textové poznámky, pokud to není z metadat zřejmé", + "codeImportedAsCode": "Importovat rozpoznané soubory s kódem (např. .json) jako poznámky s kódem, pokud to není z metadat zřejmé", + "replaceUnderscoresWithSpaces": "Nahradit podtržítka mezerami v názvech importovaných poznámek", + "import": "Import", + "failed": "Import selhal: {{message}}.", + "html_import_tags": { + "title": "HTML Import Tags", + "description": "Konfigurujte, které HTML tagy by měly být zachovány při importu poznámek. Tagy, které nejsou v tomto seznamu, budou během importu odstraněny. Některé tagy (jako 'script') jsou vždy odstraněny z bezpečnostních důvodů.", + "placeholder": "Zadejte HTML tagy, jeden na řádek", + "reset_button": "Obnovit do výchozího seznamu" + }, + "import-status": "Stav importu", + "in-progress": "Import probíhá: {{progress}}", + "successful": "Import byl úspěšně dokončen." + }, + "include_note": { + "dialog_title": "Zahrnout poznámku", + "label_note": "Poznámka", + "placeholder_search": "Hledat poznámku podle jejího názvu", + "box_size_prompt": "Velikost pole zahrnuté poznámky:", + "box_size_small": "Malý (~ 10 řádků)", + "box_size_medium": "Střední (~ 30 řádků)", + "box_size_full": "Úplný (pole zobrazuje kompletní text)", + "button_include": "Zahrnout poznámku" + }, + "info": { + "modalTitle": "Informační zpráva", + "closeButton": "Zavřít", + "okButton": "OK", + "copy_to_clipboard": "Kopírovat do schránky" + }, + "jump_to_note": { + "search_placeholder": "Hledat poznámku podle jména nebo typu > pro příkazy...", + "search_button": "Hledat v celém textu" + }, + "markdown_import": { + "dialog_title": "Markdown import", + "modal_body_text": "Vzhledem k omezením prohlížeče není možné přímo číst obsah schránky z JavaScriptu. Vložte prosím Markdown, který chcete importovat, do textového pole níže a klikněte na tlačítko Importovat", + "import_button": "Import", + "import_success": "Markdown obsah byl importován do dokumentu." + }, + "move_to": { + "dialog_title": "Přesunout poznámku do ...", + "notes_to_move": "Poznámky k přesunu", + "target_parent_note": "Cílová nadřazená poznámka", + "search_placeholder": "Hledat poznámku podle názvu", + "move_button": "Přesunout do vybrané poznámky", + "error_no_path": "Nebyla nalezena cesta pro přesun.", + "move_success_message": "Vybrané poznámky byly přesunuty do " + }, + "note_type_chooser": { + "change_path_prompt": "Změnit, kam se má nová poznámka vytvořit:", + "search_placeholder": "Hledat cestu podle názvu (výchozí, pokud je prázdná)", + "modal_title": "Vybrat typ poznámky", + "modal_body": "Vybrat typ poznámky / šablonu nové poznámky:", + "templates": "Šablony", + "builtin_templates": "Vestavěné šablony" + }, + "password_not_set": { + "title": "Heslo není nastaveno", + "body1": "Chráněné poznámky jsou šifrovány pomocí uživatelského hesla, ale heslo zatím nebylo nastaveno.", + "body2": "Pro možnost chránit poznámky klikněte na tlačítko níže a otevřete dialog Nastavení a nastavte své heslo.", + "go_to_password_options": "Přejít na možnosti hesla" + }, + "prompt": { + "title": "Výzva", + "ok": "OK", + "defaultTitle": "Výzva" + }, + "protected_session_password": { + "modal_title": "Chráněná relace", + "help_title": "Nápověda k chráněným poznámkám", + "close_label": "Zavřít", + "form_label": "Pro pokračování požadovanou akcí je třeba spustit chráněnou relaci zadáním hesla:", + "start_button": "Spustit chráněnou relaci" + }, + "recent_changes": { + "title": "Nedávné změny", + "erase_notes_button": "Vymazat smazané poznámky nyní", + "deleted_notes_message": "Smazané poznámky byly vymazány.", + "no_changes_message": "Zatím žádné změny...", + "undelete_link": "obnovit", + "confirm_undelete": "Chcete obnovit tuto poznámku a její podpoznámky?" + }, + "revisions": { + "note_revisions": "Revize poznámek", + "delete_all_revisions": "Smazat všechny revize této poznámky", + "delete_all_button": "Smazat všechny revize", + "help_title": "Nápověda k revizím poznámek", + "confirm_delete_all": "Chcete smazat všechny revize této poznámky?", + "no_revisions": "Ještě nejsou žádné revize pro tuto poznámku...", + "restore_button": "Obnovit", + "diff_on": "Zobrazit rozdíly", + "diff_off": "Zobrazit obsah", + "diff_on_hint": "Klikněte pro zobrazení rozdílů zdrojového kódu poznámky", + "diff_off_hint": "Klikněte pro zobrazení obsahu poznámky", + "diff_not_available": "Rozdíly nejsou dostupné.", + "confirm_restore": "Chcete obnovit tuto revizi? Tím se přepíše aktuální název a obsah poznámky s touto revizí.", + "delete_button": "Smazat", + "confirm_delete": "Chcete smazat tuto revizi?", + "revisions_deleted": "Revize poznámky byly smazány.", + "revision_restored": "Revize poznámky byla obnovena.", + "revision_deleted": "Revize poznámky byla smazána.", + "snapshot_interval": "Interval snímků revizí poznámky: {{seconds}}s.", + "maximum_revisions": "Limit snímků revizí poznámky: {{number}}.", + "settings": "Nastavení revizí poznámky", + "download_button": "Stáhnout", + "mime": "MIME: ", + "file_size": "Velikost souboru:", + "preview_not_available": "Náhled není dostupný pro tento typ poznámky." + }, + "sort_child_notes": { + "sort_children_by": "Seřadit dceřiné podle...", + "sorting_criteria": "Kritéria řazení", + "title": "název", + "date_created": "datum vytvoření", + "date_modified": "datum úpravy", + "sorting_direction": "Směr řazení", + "ascending": "vzestupně", + "descending": "sestupně", + "folders": "Složky", + "sort_folders_at_top": "řadit složky nahoře", + "natural_sort": "Přirozené řazení", + "sort_with_respect_to_different_character_sorting": "řadit s ohledem na různá pravidla řazení a kolace v různých jazycích nebo oblastech.", + "natural_sort_language": "Jazyk přirozeného řazení", + "the_language_code_for_natural_sort": "Jazykový kód pro přirozené řazení, např. \"zh-CN\" pro čínštinu.", + "sort": "Řazení" + }, + "upload_attachments": { + "upload_attachments_to_note": "Nahrát přílohy do poznámky", + "choose_files": "Vybrat soubory", + "files_will_be_uploaded": "Soubory budou nahrány jako přílohy do {{noteTitle}}", + "options": "Nastavení", + "shrink_images": "Zmenšit obrázky", + "upload": "Nahrát", + "tooltip": "Pokud tuto možnost zaškrtnete, Trilium se pokusí zmenšit nahrané obrázky škálováním a optimalizací, což může ovlivnit vnímanou kvalitu obrazu. Pokud není zaškrtnuta, obrázky budou nahrány beze změn." + }, + "attribute_detail": { + "attr_detail_title": "Detail Atributu", + "close_button_title": "Zrušit změny a zavřít", + "attr_is_owned_by": "Atribut je vlastněn", + "attr_name_title": "Název atributu může obsahovat pouze alfanumerické znaky, dvojtečku a podtržítko", + "name": "Název", + "value": "Hodnota", + "target_note_title": "Vazba je pojmenované spojení mezi zdrojovou poznámkou a cílovou poznámkou.", + "target_note": "Cílová poznámka", + "promoted_title": "Propagovaný atribut je zobrazen prominentně na poznámce.", + "promoted": "Propagováno", + "promoted_alias_title": "Název, který se má zobrazit v uživatelském rozhraní propagovaných atributů.", + "promoted_alias": "Alias", + "multiplicity_title": "Multiplicita definuje, kolik atributů se stejným názvem lze vytvořit – maximálně 1 nebo více než 1.", + "multiplicity": "Množnost", + "single_value": "Jedna hodnota", + "multi_value": "Více hodnot", + "label_type_title": "Typ štítku pomůže Trilium vybrat vhodné rozhraní pro zadání hodnoty štítku.", + "label_type": "Typ", + "text": "Text", + "textarea": "Víceřádkový text", + "number": "Číslo", + "boolean": "Boolean", + "date": "Datum", + "date_time": "Datum & Čas", + "time": "Čas", + "url": "URL", + "precision_title": "Kolik desetinných míst by mělo být k dispozici v rozhraní pro nastavení hodnoty.", + "precision": "Přesnost", + "digits": "číslice", + "inverse_relation_title": "Volitelné nastavení pro definování, ke které vazbě je tato inverzní. Příklad: Otec - Syn jsou inverzní vazby k sobě navzájem.", + "inverse_relation": "Inverzní vazba", + "inheritable_title": "Dědičný atribut bude zděděn všemi potomky pod tímto stromem.", + "inheritable": "Dědičný", + "save_and_close": "Uložit & zavřít Ctrl+Enter", + "delete": "Smazat", + "related_notes_title": "Další poznámky s tímto štítkem", + "more_notes": "Další poznámky", + "label": "Detail štítku", + "label_definition": "Detail definice štítku", + "relation": "Detail vazby", + "relation_definition": "Detail definice vazby", + "disable_versioning": "zakáže automatické verzování. Užitečné například pro velké, ale nepodstatné poznámky - například velké JavaScript knihovny používané pro scripting", + "calendar_root": "označí poznámku, která by měla být použita jako kořen pro denní poznámky. Pouze jedna by měla být takto označena.", + "archived": "Poznámky s tímto štítkem nebudou ve výchozím nastavení viditelné ve výsledcích vyhledávání (také v dialogových oknech Přeskočit na, Přidat odkaz atd.).", + "exclude_from_export": "Poznámky (včetně jejich podstromu) nebudou zahrnuty do žádného exportu poznámek", + "run": "Definuje, při kterých událostech se má skript spustit. Možné hodnoty jsou: \n
    \n
  • frontendStartup - když se spustí frontend Trilium (nebo se obnoví), ale ne na mobilních zařízeních.
  • \n
  • mobileStartup - když se spustí frontend Trilium (nebo se obnoví), na mobilních zařízeních.
  • \n
  • backendStartup - když se spustí backend Trilium.
  • \n
  • hourly - spustit jednou za hodinu. Můžete použít další štítek runAtHour pro určení hodiny.
  • \n
  • daily - spustit jednou denně.
  • \n
", + "run_on_instance": "Definujte, na které instanci Trilium se má toto spustit. Ve výchozím nastavení na všech instancích.", + "run_at_hour": "V kterou hodinu se má toto spustit. Mělo by se používat společně s #run=hourly. Lze definovat vícekrát pro více spuštění během dne.", + "disable_inclusion": "Skripty s tímto štítkem nebudou zahrnuty do spuštění nadřazeného skriptu.", + "sorted": "Udržuje podřízené poznámky seřazené podle názvu abecedně", + "sort_direction": "ASC (výchozí) nebo DESC", + "sort_folders_first": "Složky (poznámky s podřízenými položkami) by měly být řazeny nahoře", + "top": "Udržuje danou poznámku nahoře v rámci jejího nadřazeného (platí pouze pro seřazené nadřazené položky)", + "hide_promoted_attributes": "Skryje propagované atributy v této poznámce", + "read_only": "Editor je v režimu pouze pro čtení. Funguje pouze pro textové a kódové poznámky.", + "auto_read_only_disabled": "Textové/kódové poznámky se mohou automaticky nastavit do režimu pouze pro čtení, pokud jsou příliš velké. Toto chování můžete zakázat pro každou poznámku přidáním tohoto štítku do poznámky", + "app_css": "Označuje CSS poznámky, které jsou načteny do aplikace Trilium a mohou být tak použity k úpravě vzhledu Trilium.", + "app_theme": "Označuje CSS poznámky, které jsou kompletními motivy Trilium a jsou tak dostupné v možnostech Trilium.", + "app_theme_base": "nastavte na \"next\", \"next-light\" nebo \"next-dark\" pro použití odpovídajícího tématu TriliumNext (auto, světlé nebo tmavé) jako základu pro vlastní téma, namísto staršího.", + "css_class": "hodnota tohoto štítku je poté přidána jako CSS třída k uzlu reprezentujícímu danou poznámku ve stromu. To může být užitečné pro pokročilé tématizace. Lze použít v šablonových poznámkách.", + "icon_class": "hodnota tohoto štítku je přidána jako CSS třída k ikoně ve stromu, což může pomoci vizuálně odlišit poznámky ve stromu. Příkladem může být bx bx-home - ikony jsou převzaty z boxicons. Lze použít v šablonových poznámkách.", + "page_size": "počet položek na stránce v seznamu poznámek", + "custom_request_handler": "viz Vlastní zpracovatel požadavků", + "custom_resource_provider": "viz Vlastní zpracovatel požadavků", + "widget": "označí tuto poznámku jako vlastní widget, který bude přidán do stromu komponent Trilium", + "workspace": "označí tuto poznámku jako pracovní prostor, který umožňuje snadné zúžení zobrazení", + "workspace_icon_class": "definuje CSS třídu ikony box, která bude použita na záložce při zúžení zobrazení na tuto poznámku", + "workspace_tab_background_color": "CSS barva použitá na záložce při zúžení zobrazení na tuto poznámku", + "workspace_calendar_root": "Definuje kořenový kalendář pro pracovní prostor", + "workspace_template": "Tato poznámka se zobrazí ve výběru dostupných šablon při vytváření nové poznámky, ale pouze pokud je zúžena do pracovního prostoru obsahujícího tuto šablonu", + "search_home": "nové poznámky k vyhledávání budou vytvořeny jako podřízené položky této poznámky", + "workspace_search_home": "při přesunutí do některé nadřazené poznámky tohoto pracovního prostoru budou vytvořeny nové poznámky k vyhledávání jako podřízené této poznámky", + "inbox": "výchozí umístění schránky pro nové poznámky – pokud vytvoříte poznámku pomocí tlačítka „Nová poznámka“ v postranním panelu, poznámky se uloží jako podřízené poznámky k poznámce označené štítkem #inbox.", + "workspace_inbox": "výchozí umístění doručené pošty pro nové poznámky při přesunutí do některé nadřazené poznámky tohoto pracovního prostoru", + "sql_console_home": "výchozí umístění poznámky konzole SQL", + "bookmark_folder": "poznámka s tímto štítkem se zobrazí v záložkách jako složka (umožňuje přístup k jejím podřízeným poznámkám)", + "share_hidden_from_tree": "Tato poznámka je skrytá z levého navigačního stromu, ale je stále přístupná pomocí její URL", + "share_external_link": "poznámka bude fungovat jako odkaz na externí webovou stránku ve sdíleném stromu", + "share_alias": "definujte alias, pod kterým bude poznámka dostupná na https://your_trilium_host/share/[your_alias]", + "share_omit_default_css": "výchozí CSS stránky pro sdílení bude vynechána. Použijte, pokud provedete rozsáhlé změny stylu.", + "share_root": "Označuje poznámku, která je obsluhována z kořene /share.", + "share_description": "Definujte text, který má být přidán do meta tagu HTML pro popis", + "share_raw": "poznámka bude obsluhována v surovém formátu, bez obalu HTML", + "share_disallow_robot_indexing": "zakáže indexování této poznámky roboty pomocí hlavičky X-Robots-Tag: noindex", + "share_credentials": "Vyžaduje pověření pro přístup k této sdílené poznámce. Hodnota se očekává ve formátu 'username:password'. Nezapomeňte ji učinit dědičnou, aby se použila na podřízené poznámky/obrázky.", + "share_index": "poznámka s tímto štítkem zobrazí všechny kořeny sdílených poznámek", + "display_relations": "seznam jmen vazeb oddělených čárkami, které se mají zobrazit. Všechny ostatní budou skryté.", + "hide_relations": "Seznam jmen vazeb oddělených čárkami, které se mají skrýt. Všechny ostatní budou zobrazeny.", + "title_template": "výchozí název poznámek vytvořených jako podřízené této poznámce. Hodnota je vyhodnocena jako řetězec v JavaScriptu \n a lze ji tedy obohatit o dynamický obsah pomocí vložených proměnných now a parentNote. Příklady:\n \n
    \n
  • ${parentNote.getLabelValue(‚authorName‘)}ova literární díla
  • \n
  • Záznam pro ${now.format(‚YYYY-MM-DD HH:mm:ss‘)}
  • \n
\n \n Viz wiki s podrobnostmi, dokumentaci API pro parentNote a now pro podrobnosti.", + "template": "Tato poznámka se zobrazí ve výběru dostupných šablon při vytváření nové poznámky", + "toc": "#toc nebo #toc=show vynutí zobrazení Obsahu, #toc=hide vynutí jeho skrytí. Pokud štítek neexistuje, je respektováno globální nastavení", + "color": "Definuje barvu poznámky ve stromu poznámek, odkazech atd. Použijte jakoukoli platnou hodnotu CSS barvy, například 'red' nebo #a13d5f", + "keyboard_shortcut": "Definuje klávesovou zkratku, která okamžitě skočí na tuto poznámku. Příklad: 'ctrl+alt+e'. Pro projev změny je vyžadováno obnovení frontendu.", + "keep_current_hoisting": "Otevření tohoto odkazu nezmění zúžení zobrazení, i když poznámka není zobrazitelná v aktuálním zúženém podstromu.", + "execute_button": "Název tlačítka, které spustí aktuální poznámku s kódem", + "execute_description": "Delší popis aktuální poznámky s kódem zobrazený spolu s tlačítkem pro spuštění", + "exclude_from_note_map": "Poznámky s tímto štítkem budou skryté v Mapě poznámek", + "new_notes_on_top": "Nové poznámky budou vytvářeny nahoře nadřazené poznámky, nikoli dole.", + "hide_highlight_widget": "Skrýt Widget Seznam zvýraznění", + "run_on_note_creation": "spustí se při vytvoření poznámky na serveru. Tuto relaci použijte, pokud chcete skript spustit pro všechny poznámky vytvořené v rámci konkrétního podstromu. V takovém případě ji vytvořte na kořenové poznámce podstromu a nastavte ji jako dědičnou. Skript se spustí při vytvoření nové poznámky v rámci podstromu (v jakékoli úrovni).", + "run_on_child_note_creation": "provede se, když je pod poznámkou, ve které je tento vztah definován, vytvořena nová poznámka", + "run_on_note_title_change": "spustí se při změně názvu poznámky (včetně vytvoření poznámky)", + "run_on_note_content_change": "spustí se při změně obsahu poznámky (včetně jejího vytvoření).", + "run_on_note_change": "spustí se při změně noty (včetně jejího vytvoření). Nezahrnuje změny obsahu", + "run_on_note_deletion": "spustí se při mazání poznámky", + "run_on_branch_creation": "spustí se při vytvoření větve. Větev je propojení mezi nadřazenou a podřízenou poznámkou a vzniká například při klonování nebo přesouvání poznámky.", + "run_on_branch_change": "Spustí se při aktualizaci větve.", + "run_on_branch_deletion": "spustí se při smazání větve. Větev představuje propojení mezi nadřazenou a podřízenou poznámkou a je smazána např. při přesunu poznámky (původní větev/propojení je smazáno).", + "run_on_attribute_creation": "spustí se při vytvoření nového atributu pro poznámku, která definuje tuto vazbu", + "relation_template": "atributy poznámky budou zděděny i bez vztahu rodič-potomek; obsah poznámky a její podstrom budou přidány do instancí poznámek, pokud jsou prázdné. Podrobnosti najdete v dokumentaci.", + "inherit": "Atributy poznámky budou zděděny i bez vztahu rodič–potomek. Podobný koncept najdete v sekci „Vazby šablon“. Více informací najdete v dokumentaci v části „Dědičnost atributů“.", + "render_note": "Poznámky typu „zobrazit HTML poznámku“ budou zobrazeny pomocí kódové poznámky (HTML nebo skript) a je nutné pomocí této vazby určit, která poznámka se má zobrazit", + "widget_relation": "cíl této vazby bude proveden a zobrazen jako widget v postranním panelu", + "share_css": "CSS poznámka, která bude vložena do sdílené stránky. CSS poznámka musí být také v sdíleném podstromu. Zvažte použití 'share_hidden_from_tree' a 'share_omit_default_css'.", + "share_js": "JavaScript poznámka, která bude vložena do sdílené stránky. JS poznámka musí být také v sdíleném podstromu. Zvažte použití 'share_hidden_from_tree'.", + "share_template": "Vložená JavaScript poznámka, která bude použita jako šablona pro zobrazení sdílené poznámky. Vrací se k výchozí šabloně. Zvažte použití 'share_hidden_from_tree'.", + "share_favicon": "Poznámka s favicon, která bude nastavena na sdílené stránce. Obvykle ji chcete nastavit do kořene sdílení a učinit ji dědičnou. Favicon poznámka musí být také v sdíleném podstromu. Zvažte použití 'share_hidden_from_tree'.", + "is_owned_by_note": "je vlastněna poznámkou", + "other_notes_with_name": "Ostatní poznámky s {{attributeType}} názvem \"{{attributeName}}\"", + "and_more": "... a {{count}} dalších.", + "print_landscape": "Při exportu do ⟨PDF⟩ změní orientaci stránky na landscape místo portrait.", + "print_page_size": "Při exportu do ⟨PDF⟩ změní velikost stránky. Podporované hodnoty: A0, A1, A2, A3, A4, A5, A6, Legal, Letter, Tabloid, Ledger.", + "color_type": "Barva", + "run_on_attribute_change": " spustí se při změně atributu poznámky, která tuto vazbu definuje. Spustí se také při smazání tohoto atributu" + }, + "attribute_editor": { + "help_text_body1": "Pro přidání štítku stačí zadat např. #rock nebo pokud chcete přidat i hodnotu, např. #year = 2020", + "help_text_body2": "Pro vazbu zadejte ~author = @, což by mělo vyvolat automatické doplňování, kde můžete vyhledat požadovanou poznámku.", + "help_text_body3": "Případně můžete štítek a vazbu přidat pomocí tlačítka + na pravé straně.", + "save_attributes": "Uložit ⟨Atributy⟩ ", + "add_a_new_attribute": "Přidat nový ⟨Atribut⟩", + "add_new_label": "Přidat nový štítek ", + "add_new_relation": "Přidat novou vazbu ", + "add_new_label_definition": "Přidat novou definici štítku", + "add_new_relation_definition": "Přidat novou definici vazby", + "placeholder": "Zadejte štítky a vazby zde" + }, + "abstract_bulk_action": { + "remove_this_search_action": "Odebrat tuto akci hledání" + }, + "execute_script": { + "execute_script": "Spustit skript", + "help_text": "Můžete spustit jednoduché skripty na vybraných poznámkách.", + "example_1": "Například pro připojení řetězce k názvu poznámky použijte tento malý skript:", + "example_2": "Složitější příklad by bylo smazání všech atributů vybraných poznámek:" + }, + "add_label": { + "add_label": "Přidat štítek", + "label_name_placeholder": "Název štítku", + "label_name_title": "Povolené znaky jsou alfanumerické znaky, podtržítko a dvojtečka.", + "to_value": "k hodnotě", + "new_value_placeholder": "nová hodnota", + "help_text": "Na všech odpovídajících poznámkách:", + "help_text_item1": "vytvořit daný štítek, pokud jej poznámka ještě nemá", + "help_text_item2": "nebo změnit hodnotu existujícího štítku", + "help_text_note": "Můžete také zavolat tuto metodu bez hodnoty, v takovém případě bude štítek přiřazen k poznámce bez hodnoty." + }, + "delete_label": { + "delete_label": "Smazat štítek", + "label_name_placeholder": "název štítku", + "label_name_title": "Povolené znaky jsou alfanumerické znaky, podtržítko a dvojtečka." + }, + "rename_label": { + "rename_label": "Přejmenovat štítek", + "rename_label_from": "Přejmenovat štítek z", + "old_name_placeholder": "starý název", + "to": "Na", + "new_name_placeholder": "nový název", + "name_title": "Povolené znaky jsou alfanumerické znaky, podtržítko a dvojtečka." + }, + "update_label_value": { + "update_label_value": "Aktualizovat hodnotu štítku", + "label_name_placeholder": "název štítku", + "label_name_title": "Povolené znaky jsou alfanumerické znaky, podtržítko a dvojtečka.", + "to_value": "na hodnotu", + "new_value_placeholder": "nová hodnota", + "help_text": "U všech nalezených poznámek změňte hodnotu existujícího štítku.", + "help_text_note": "Tuto metodu můžete také zavolat bez hodnoty, v takovém případě bude štítek přiřazen k poznámce bez hodnoty." + }, + "delete_note": { + "delete_note": "Smazat poznámku", + "delete_matched_notes": "Smazat nalezené poznámky", + "delete_matched_notes_description": "Tímto se smažou nalezené poznámky.", + "undelete_notes_instruction": "Po smazání je lze obnovit z dialogu Recent Changes.", + "erase_notes_instruction": "Pro trvalé vymazání poznámek můžete po smazání přejít do Option -> Other a kliknout na tlačítko \"Vymazat smazané poznámky nyní\"." + }, + "delete_revisions": { + "delete_note_revisions": "Smazat revize poznámek", + "all_past_note_revisions": "Všechny minulé revize nalezených poznámek budou smazány. Poznámka samotná zůstane plně zachována. Jinými slovy, historie poznámky bude odstraněna." + }, + "move_note": { + "move_note": "Přesunout poznámku", + "to": "do", + "target_parent_note": "cílové nadřazené poznámky", + "on_all_matched_notes": "Na všech odpovídajících poznámkách", + "move_note_new_parent": "přesunout poznámku do nové nadřazené složky, pokud má poznámka pouze jednu nadřazenou složku (tj. stará větev je odstraněna a je vytvořena nová větev vedoucí do nové nadřazené složky)", + "clone_note_new_parent": "klonovat poznámku do novéhé nadřazené složky, pokud má poznámka více klonů/větví (není jasné, kterou větev by mělo odstranit)", + "nothing_will_happen": "nic se nestane, pokud nelze poznámku přesunout do cílové poznámky (tj. to by vytvořilo cyklus ve stromu)" + }, + "rename_note": { + "rename_note": "Přejmenovat poznámku", + "rename_note_title_to": "Přejmenovat název poznámky na", + "new_note_title": "nový název poznámky", + "click_help_icon": "Klikněte na ikonu nápovědy vpravo a zobrazte všechny možnosti", + "evaluated_as_js_string": "Zadaná hodnota je vyhodnocena jako JavaScript řetězec a může být tak obohacena o dynamický obsah pomocí vložené proměnné note (poznámka bude přejmenována). Příklady:", + "example_note": "Poznámka - všechny odpovídající poznámky jsou přejmenovány na 'Poznámka'", + "example_new_title": "NOVÝ: ${note.title} - názvy odpovídajících poznámek mají předponu 'NOVÝ: '", + "example_date_prefix": "${note.dateCreatedObj.format('MM-DD:')}: ${note.title} - před názvem nalezených poznámek je uvedeno datum a měsíc jejich vytvoření", + "api_docs": "Podrobnosti najdete v dokumentaci k API v poznámce a u jejích vlastností dateCreatedObj / utcDateCreatedObj." + }, + "add_relation": { + "add_relation": "Přidat vazbu", + "relation_name": "název vazby", + "allowed_characters": "Povolené znaky jsou alfanumerické znaky, podtržítko a dvojtečka.", + "to": "do", + "target_note": "cílová poznámka", + "create_relation_on_all_matched_notes": "U všech shodných not vytvoř dannou vazbu." + }, + "delete_relation": { + "delete_relation": "Smazat vazbu", + "relation_name": "název vazby", + "allowed_characters": "Povolené znaky jsou alfanumerické znaky, podtržítko a dvojtečka." + }, + "rename_relation": { + "rename_relation": "Přejmenovat vazbu", + "rename_relation_from": "Přejmenovat vazbu z", + "old_name": "starý název", + "to": "Na", + "new_name": "nový název", + "allowed_characters": "Povolené znaky jsou alfanumerické znaky, podtržítko a dvojtečka." + }, + "update_relation_target": { + "update_relation": "Aktualizovat vazbu", + "relation_name": "název vazby", + "allowed_characters": "Povolené znaky jsou alfanumerické znaky, podtržítko a dvojtečka.", + "to": "do", + "target_note": "cílová poznámka", + "on_all_matched_notes": "Na všech odpovídajících poznámkách", + "change_target_note": "změnit cílovou poznámku existující vazby", + "update_relation_target": "Aktualizovat cílovou vazbu" + }, + "attachments_actions": { + "open_externally": "Otevřít externě", + "open_externally_title": "Soubor bude otevřen v externí aplikaci a sledován na změny. Poté budete moci nahrát upravenou verzi zpět do Trilium.", + "open_custom": "Otevřít vlastní", + "open_custom_title": "Soubor bude otevřen v externí aplikaci a sledován na změny. Poté budete moci nahrát upravenou verzi zpět do Trilium.", + "download": "Stáhnout", + "rename_attachment": "Přejmenovat přílohu", + "upload_new_revision": "Nahrát novou revizi", + "copy_link_to_clipboard": "Kopírovat odkaz do schránky", + "convert_attachment_into_note": "Převést přílohu na poznámku", + "delete_attachment": "Smazat přílohu", + "upload_success": "Nová revize přílohy byla nahrána.", + "upload_failed": "Nahrání nové revize přílohy selhalo.", + "open_externally_detail_page": "Otevření přílohy externě je dostupné pouze ze stránky s detaily, nejprve klikněte na detail přílohy a akci opakujte.", + "open_custom_client_only": "Vlastní otevření příloh lze provést pouze z desktop klienta.", + "delete_confirm": "Jste si jisti, že chcete smazat přílohu '{{title}}'?", + "delete_success": "Příloha '{{title}}' byla smazána.", + "convert_confirm": "Jste si jisti, že chcete převést přílohu '{{title}}' na samostatnou Poznámku?", + "convert_success": "Příloha '{{title}}' byla převedena na Poznámku.", + "enter_new_name": "Zadejte nový název přílohy" + }, + "calendar": { + "mon": "Po", + "tue": "Út", + "wed": "St", + "thu": "Čt", + "fri": "Pá", + "sat": "So", + "sun": "Ne", + "cannot_find_day_note": "Nelze najít denní poznámku", + "cannot_find_week_note": "Nelze najít týdenní poznámku", + "january": "Leden", + "february": "Únor", + "march": "Březen", + "april": "Duben", + "may": "Květen", + "june": "Červen", + "july": "Červenec", + "august": "Srpen", + "september": "Září", + "october": "Říjen", + "november": "Listopad", + "december": "Prosinec", + "week": "Týden", + "week_previous": "Předchozí týden", + "week_next": "Další týden", + "month": "Měsíc", + "month_previous": "Předchozí měsíc", + "month_next": "Další měsíc", + "year": "Rok", + "year_previous": "Předchozí rok", + "year_next": "Další rok", + "list": "Seznam", + "today": "Dnes" + }, + "close_pane_button": { + "close_this_pane": "Zavřít tento panel" + }, + "create_pane_button": { + "create_new_split": "Vytvořit nové rozdělení" + }, + "edit_button": { + "edit_this_note": "Upravit tuto poznámku" + }, + "show_toc_widget_button": { + "show_toc": "Zobrazit Obsah" + }, + "show_highlights_list_widget_button": { + "show_highlights_list": "Zobrazit Seznam zvýraznění" + }, + "global_menu": { + "menu": "Menu", + "options": "Nastavení", + "open_new_window": "Otevřít Nové Okno", + "switch_to_mobile_version": "Přepnout na Mobilní Verzi", + "switch_to_desktop_version": "Přepnout na Počítačovou Verzi", + "zoom": "Zoom", + "toggle_fullscreen": "Přepnout Celou Obrazovku", + "zoom_out": "Oddálit", + "reset_zoom_level": "Resetovat Úroveň Zoomu", + "zoom_in": "Přiblížit", + "configure_launchbar": "Konfigurovat Spouštěcí Lištu", + "show_shared_notes_subtree": "Zobrazit Podstrom Sdílených Poznámek", + "advanced": "Pokročilé", + "open_dev_tools": "Otevřít Nástroje pro vývojáře", + "open_sql_console": "Otevřít SQL Konzoli", + "open_sql_console_history": "Otevřít Historii SQL Konzole", + "open_search_history": "Otevřít Historii Hledání", + "show_backend_log": "Zobrazit Log Backendu", + "reload_hint": "Obnovení může pomoci s některými vizuálními chybami bez restartování celé aplikace.", + "reload_frontend": "Obnovit Frontend", + "show_hidden_subtree": "Zobrazit Skrytý Podstrom", + "show_help": "Zobrazit Nápovědu", + "about": "O Trilium Notes", + "logout": "Odhlásit se", + "show-cheatsheet": "Zobrazit Cheatsheet", + "toggle-zen-mode": "Zen Režim", + "new-version-available": "Je k dispozici nová aktualizace", + "download-update": "Získat verzi {{latestVersion}}", + "search_notes": "Hledání poznámek" + }, + "zen_mode": { + "button_exit": "Opustit Zen mód" + }, + "sync_status": { + "unknown": "

Stav synchronizace bude znám po spuštění dalšího pokusu o synchronizaci.

Klikněte pro spuštění synchronizace nyní.

", + "connected_with_changes": "

Připojeno k synchronizačnímu serveru.
Existují některé nedokončené změny, které je třeba synchronizovat.

Klikněte pro spuštění synchronizace.

", + "connected_no_changes": "

Připojeno k synchronizačnímu serveru.
Všechny změny již byly synchronizovány.

Klikněte pro spuštění synchronizace.

", + "disconnected_with_changes": "

Nepodařilo se navázat spojení se synchronizačním serverem.
Existují některé nedokončené změny, které je třeba synchronizovat.

Klikněte pro spuštění synchronizace.

", + "disconnected_no_changes": "

Nepodařilo se navázat spojení se synchronizačním serverem.
Všechny známé změny byly synchronizovány.

Klikněte pro spuštění synchronizace.

", + "in_progress": "Probíhá synchronizace se serverem." + }, + "left_pane_toggle": { + "show_panel": "Zobrazit panel", + "hide_panel": "Skrýt panel" + }, + "move_pane_button": { + "move_left": "Posunout vlevo", + "move_right": "Posunout vpravo" + }, + "note_actions": { + "convert_into_attachment": "Převést na přílohu", + "re_render_note": "Znovu vykreslit poznámku", + "search_in_note": "Hledat v poznámce", + "note_source": "Zdroj poznámky", + "note_attachments": "Přílohy poznámky", + "view_ocr_text": "Zobrazit text z OCR", + "open_note_externally": "Otevřít poznámku externě", + "open_note_externally_title": "Soubor bude otevřen v externí aplikaci a sledován na změny. Poté budete moci nahrát upravenou verzi zpět do Trilium.", + "open_note_custom": "Otevřít poznámku vlastním způsobem", + "open_note_on_server": "Otevřít poznámku na serveru", + "import_files": "Importovat soubory", + "export_note": "Exportovat poznámku", + "delete_note": "Smazat poznámku", + "print_note": "Vytisknout poznámku", + "view_revisions": "Revize poznámky...", + "save_revision": "Uložit revizi", + "advanced": "Pokročilé", + "convert_into_attachment_failed": "Konverze poznámky '{{title}}' selhala.", + "convert_into_attachment_successful": "Poznámka '{{title}}' byla převedena na přílohu.", + "convert_into_attachment_prompt": "Jste si jisti, že chcete převést poznámku '{{title}}' na přílohu nadřazené poznámky?", + "print_pdf": "Exportovat jako PDF...", + "export_as_image": "Exportovat jako obrázek", + "export_as_image_png": "PNG (raster)", + "export_as_image_svg": "SVG (vector)", + "note_map": "Mapa poznámek" + }, + "onclick_button": { + "no_click_handler": "Widget tlačítka '{{componentId}}' nemá definovaný obslužný program kliknutí" + }, + "protected_session_status": { + "active": "Chráněná relace je aktivní. Klikněte pro ukončení chráněné relace.", + "inactive": "Klikněte pro vstup do chráněné relace" + }, + "revisions_button": { + "note_revisions": "Revize poznámek" + }, + "update_available": { + "update_available": "Dostupná aktualizace" + }, + "note_launcher": { + "this_launcher_doesnt_define_target_note": "Tento spouštěč nedefinuje cílovou poznámku." + }, + "code_buttons": { + "execute_button_title": "Spustit skript", + "trilium_api_docs_button_title": "Otevřít dokumentaci Trilium API", + "save_to_note_button_title": "Uložit do poznámky", + "opening_api_docs_message": "Otevírám API dokumentaci...", + "sql_console_saved_message": "Poznámka SQL konzole byla uložena do {{note_path}}" + }, + "copy_image_reference_button": { + "button_title": "Kopírovat odkaz na obrázek do schránky, lze vložit do textové poznámky." + }, + "hide_floating_buttons_button": { + "button_title": "Skrýt tlačítka" + }, + "show_floating_buttons_button": { + "button_title": "Zobrazit tlačítka" + }, + "svg_export_button": { + "button_title": "Exportovat diagram jako SVG" + }, + "relation_map_buttons": { + "create_child_note_title": "Vytvořit dceřinou poznámku a přidat ji na mapu", + "reset_pan_zoom_title": "Resetovat posun & zoom na počáteční souřadnice a zvětšení", + "zoom_in_title": "Přiblížit", + "zoom_out_title": "Oddálit" + }, + "mobile_detail_menu": { + "insert_child_note": "Vložit dceřinou poznámku", + "delete_this_note": "Smazat tuto poznámku", + "note_revisions": "Revize poznámky", + "error_cannot_get_branch_id": "Nelze získat branchId pro cestu k poznámce '{{notePath}}'", + "error_unrecognized_command": "Nerozpoznaný příkaz {{command}}", + "backlinks": "Zpětné odkazy", + "content_language_switcher": "Jazyk obsahu: {{language}}" + }, + "note_icon": { + "change_note_icon": "Změnit ikonu poznámky", + "search": "Hledání:", + "search_placeholder_filtered": "Hledání {{number}} ikon v {{name}}", + "reset-default": "Obnovit na výchozí ikonu", + "filter": "Filtr", + "filter-none": "Všechny ikony", + "filter-default": "Výchozí ikony", + "icon_tooltip": "{{name}}\nBalíček ikon: {{iconPack}}", + "no_results": "Žádné ikony nenalezeny.", + "search_placeholder_one": "Najít {{number}} ikonu v {{count}} balíčcích", + "search_placeholder_few": "Najít {{number}} ikony v {{count}} balíčcích", + "search_placeholder_other": "Najít {{number}} ikon v {{count}} balíčcích" + }, + "basic_properties": { + "note_type": "Typ poznámky", + "editable": "Upravitelné", + "basic_properties": "Základní vlastnosti", + "language": "Jazyk", + "configure_code_notes": "Konfigurovat poznámky s kódem..." + }, + "book_properties": { + "view_type": "Typ zobrazení", + "grid": "Mřížka", + "list": "Seznam", + "collapse_all_notes": "Sbalit všechny poznámky", + "expand_tooltip": "Rozbalí přímé podprvky této kolekce (do hloubky jedné úrovně). Další možnosti zobrazíte kliknutím na šipku vpravo.", + "collapse": "Sbalit", + "expand": "Rozbalit", + "expand_first_level": "Rozbalit přímé potomky", + "expand_nth_level": "Rozbalit {{depth}} úrovně", + "expand_all_levels": "Rozbalit všechny úrovně", + "book_properties": "Vlastnosti kolekce", + "invalid_view_type": "Neplatný typ zobrazení '{{type}}'", + "calendar": "Kalendář", + "table": "Tabulka", + "geo-map": "Geomapa", + "board": "Tabule", + "presentation": "Prezentace", + "include_archived_notes": "Zobrazit archivované Poznámky", + "hide_child_notes": "Skrýt dceřiné Poznámky ve Stromu" + }, + "edited_notes": { + "no_edited_notes_found": "Zatím nebyly upraveny žádné Poznámky v tento den...", + "title": "Upravené Poznámky", + "deleted": "(smazáno)" + }, + "file_properties": { + "note_id": "ID Poznámky", + "original_file_name": "Původní název souboru", + "file_type": "Typ souboru", + "file_size": "Velikost souboru", + "download": "Stáhnout", + "open": "Otevřít externě", + "upload_new_revision": "Nahrát novou revizi", + "upload_success": "Nová revize souboru byla nahrána.", + "upload_failed": "Nahrání nové revize souboru selhalo.", + "title": "Soubor" + }, + "image_properties": { + "original_file_name": "Původní název souboru", + "file_type": "Typ souboru", + "file_size": "Velikost souboru", + "download": "Stáhnout", + "open": "Otevřít", + "copy_reference_to_clipboard": "Kopírovat referenci do schránky", + "upload_new_revision": "Nahrát novou revizi", + "upload_success": "Nová revize obrázku byla nahrána.", + "upload_failed": "Nahrání nové revize obrázku selhalo: {{message}}", + "title": "Obrázek" + }, + "inherited_attribute_list": { + "title": "Zděděné atributy", + "no_inherited_attributes": "Žádné zděděné atributy.", + "none": "žádný" + }, + "note_info_widget": { + "note_id": "ID Poznámky", + "created": "Vytvořeno", + "modified": "Upraveno", + "type": "Typ", + "mime": "MIME typ", + "note_size": "Velikost Poznámky", + "note_size_info": "Velikost Poznámky poskytuje hrubý odhad požadavků na úložiště pro tuto poznámku. Bere v úvahu obsah poznámky a obsah jejích revizí.", + "calculate": "vypočítat", + "subtree_size": "(velikost podstromu: {{size}} v {{count}} poznámkách)", + "title": "Informace o Poznámce", + "show_similar_notes": "Zobrazit podobné Poznámky" + }, + "note_map": { + "open_full": "Rozbalit na plnou velikost", + "collapse": "Sbalit na normální velikost", + "title": "Mapa poznámek", + "fix-nodes": "Opravit uzly", + "link-distance": "Vzdálenost propojení" + }, + "note_paths": { + "title": "Cesty k poznámkám", + "clone_button": "Klonovat poznámku na nové místo...", + "intro_placed": "Tato poznámka je umístěna v následujících cestách:", + "intro_not_placed": "Tato poznámka ještě nebyla umístěna do stromu poznámek.", + "outside_hoisted": "Tato cesta je mimo nadřazenou poznámku a bude nutné ji odnadřazit.", + "archived": "Archivováno", + "search": "Hledání" + }, + "note_properties": { + "this_note_was_originally_taken_from": "Tato poznámka byla původně pořízena z:", + "info": "Info" + }, + "owned_attribute_list": { + "owned_attributes": "Vlastní atributy" + }, + "promoted_attributes": { + "promoted_attributes": "Propagované atributy", + "unset-field-placeholder": "není nastaveno", + "url_placeholder": "http://website...", + "open_external_link": "Otevřít externí odkaz", + "unknown_label_type": "Neznámý typ štítku '{{type}}'", + "unknown_attribute_type": "Neznámý typ atributu '{{type}}'", + "add_new_attribute": "Přidat nový atribut", + "remove_this_attribute": "Odebrat tento atribut", + "remove_color": "Odebrat barevný štítek" + }, + "script_executor": { + "query": "Dotaz", + "script": "Skript", + "execute_query": "Spustit dotaz", + "execute_script": "Spustit skript" + }, + "search_definition": { + "add_search_option": "Přidat možnost hledání:", + "search_string": "vyhledávací řetězec", + "search_script": "skript pro hledání", + "ancestor": "předek", + "fast_search": "rychlé hledání", + "fast_search_description": "Možnost rychlého hledání vypne úplné textové prohledávání obsahu poznámek, což může urychlit hledání ve velkých databázích.", + "include_archived": "zahrnout archivované", + "include_archived_notes_description": "Archivované poznámky jsou ve výchozím nastavení vyloučeny z výsledků hledání, s touto možností budou zahrnuty.", + "order_by": "seřadit podle", + "limit": "limit", + "limit_description": "Omezit počet výsledků", + "debug": "ladění", + "debug_description": "Ladění vypíše do konzole další ladicí informace, které pomohou při ladění složitých dotazů", + "action": "akce", + "option": "možnost", + "search_button": "Hledání", + "search_execute": "Hledání & Spuštění akcí", + "save_to_note": "Uložit do poznámky", + "search_parameters": "Parametry hledání", + "unknown_search_option": "Neznámá možnost hledání {{searchOptionName}}", + "search_note_saved": "Hledání poznámky bylo uloženo do {{- notePathTitle}}", + "actions_executed": "Akce byly provedeny.", + "view_options": "Možnosti zobrazení:" + }, + "similar_notes": { + "title": "Podobné poznámky", + "no_similar_notes_found": "Nebyly nalezeny žádné podobné poznámky." + }, + "abstract_search_option": { + "remove_this_search_option": "Odebrat tuto možnost hledání", + "failed_rendering": "Selhalo vykreslení možnosti hledání: {{dto}} s chybou: {{error}} {{stack}}" + }, + "ancestor": { + "label": "Předek", + "placeholder": "hledat poznámku podle jejího názvu", + "depth_label": "hloubka", + "depth_doesnt_matter": "nezáleží na tom", + "depth_eq": "je přesně {{count}}", + "direct_children": "přímé děti", + "depth_gt": "je větší než {{count}}", + "depth_lt": "je menší než {{count}}" + }, + "debug": { + "debug": "Ladění", + "debug_info": "Ladění vypíše další ladicí informace do konzole, které pomohou při ladění složitých dotazů.", + "access_info": "Pro přístup k ladicím informacím spusťte dotaz a klikněte na \"Zobrazit backend log\" v levém horním rohu." + }, + "fast_search": { + "fast_search": "Rychlé hledání", + "description": "Možnost rychlého hledání vypne úplné prohledávání obsahu poznámek, což může urychlit hledání ve velkých databázích." + }, + "include_archived_notes": { + "include_archived_notes": "Zahrnout archivované poznámky" + }, + "limit": { + "limit": "Limit", + "take_first_x_results": "Zobrazí pouze prvních X zadaných výsledků." + }, + "order_by": { + "order_by": "Seřadit podle", + "relevancy": "Relevance (výchozí)", + "title": "Název", + "date_created": "Datum vytvoření", + "date_modified": "Datum poslední modifikace", + "content_size": "Velikost obsahu Poznámky", + "content_and_attachments_size": "Velikost obsahu Poznámky včetně Příloh", + "content_and_attachments_and_revisions_size": "Velikost obsahu Poznámky včetně Příloh a Revizí", + "revision_count": "Počet Revizí", + "children_count": "Počet Dceřiných Poznámek", + "parent_count": "Počet Klonů", + "owned_label_count": "Počet Štítků", + "owned_relation_count": "Počet Vazeb", + "target_relation_count": "Počet Vazeb cílených na Poznámku", + "random": "Náhodné pořadí", + "asc": "Vzestupně (výchozí)", + "desc": "Sestupně" + }, + "search_script": { + "title": "Skript pro hledání:", + "placeholder": "hledat Poznámku podle jejího názvu", + "description1": "Vyhledávací skript umožňuje definovat výsledky vyhledávání spuštěním skriptu. To poskytuje maximální flexibilitu v případech, kdy standardní vyhledávání nestačí.", + "description2": "Vyhledávací skript musí být typu „code“ a podtypu „JavaScript backend“. Skript musí vracet pole noteIds nebo notes.", + "example_title": "Podívejte se na tento příklad:", + "example_code": "// 1. Předběžné filtrování pomocí standardního vyhledávání\nconst candidateNotes = api.searchForNotes(„#journal“); \n\n// 2. Použití vlastních vyhledávacích kritérií\nconst matchedNotes = candidateNotes\n .filter(note => note.title.match(/[0-9]{1,2}\\. ?[0-9]{1,2}\\. ?[0-9]{4}/));\n\nreturn matchedNotes;", + "note": "Upozorňujeme, že vyhledávací skript a vyhledávací řetězec nelze vzájemně kombinovat." + }, + "search_string": { + "title_column": "Vyhledávací řetězec:", + "placeholder": "fulltext klíčová slova, #tag = hodnota...", + "search_syntax": "Syntaxe vyhledávání", + "also_see": "také viz", + "complete_help": "kompletní nápověda k syntaxi vyhledávání", + "full_text_search": "Stačí zadat jakýkoli text pro fulltextové vyhledávání", + "label_abc": "vrací poznámky se stítkem abc", + "label_year": "vyhledá poznámky, u nichž má štítek roku hodnotu 2019", + "label_rock_pop": "vyhledá poznámky, které mají štítek rock i pop", + "label_rock_or_pop": "stačí, aby byl přítomen jeden ze štítků", + "label_year_comparison": "numerické porovnání (také >, >=, <).", + "label_date_created": "poznámky vytvořené za poslední měsíc", + "error": "Chyba vyhledávání: {{error}}", + "search_prefix": "Hledání:" + }, + "attachment_detail": { + "open_help_page": "Otevřít nápovědu k přílohám", + "owning_note": "Vlastní poznámka: ", + "you_can_also_open": ", můžete také otevřít ", + "list_of_all_attachments": "Seznam všech příloh", + "attachment_deleted": "Tato příloha byla smazána." + }, + "attachment_list": { + "open_help_page": "Otevřít nápovědu k přílohám", + "owning_note": "Vlastní poznámka: ", + "upload_attachments": "Nahrát přílohy", + "no_attachments": "Tato poznámka nemá žádné přílohy." + }, + "book": { + "no_children_help": "Tato kolekce nemá žádné dceřiné poznámky, takže není co zobrazit.", + "drag_locked_title": "Uzamčeno pro úpravy", + "drag_locked_message": "Přetahování není povoleno, protože kolekce je uzamčena pro úpravy." + }, + "editable_code": { + "placeholder": "Zadejte obsah své poznámky s kódem zde..." + }, + "editable_text": { + "placeholder": "Zadejte obsah své poznámky zde...", + "editor_crashed_title": "Editor textu havaroval", + "editor_crashed_content": "Váš obsah byl úspěšně obnoven, ale několik vašich posledních změn nemuselo být uloženo.", + "editor_crashed_details_button": "Zobrazit více detailů...", + "editor_crashed_details_intro": "Pokud se tato chyba vyskytne několikrát, zvažte její nahlášení na GitHub vložením informací níže.", + "editor_crashed_details_title": "Technické informace", + "auto-detect-language": "Automaticky detekováno", + "keeps-crashing": "Komponenta pro úpravy opakovaně havaruje. Zkuste restartovat Trilium. Pokud problém přetrvává, zvažte vytvoření hlášení o chybě." + }, + "empty": { + "open_note_instruction": "Otevřete poznámku zadáním názvu poznámky do pole níže nebo vyberte poznámku ve stromu.", + "search_placeholder": "hledat poznámku podle jejího názvu", + "enter_workspace": "Vstup do pracovního prostoru {{title}}" + }, + "file": { + "file_preview_not_available": "Náhled souboru není dostupný pro tento formát souboru.", + "too_big": "Náhled zobrazuje pouze prvních {{maxNumChars}} znaků souboru z důvodu výkonu. Stáhněte si soubor a otevřete jej externě, abyste mohli zobrazit celý obsah." + }, + "media": { + "play": "Přehrát (Space)", + "pause": "Pozastavit (Space)", + "back-10s": "Zpět o 10s (Šipka doleva)", + "forward-30s": "Dopředu o 30s", + "mute": "Ztlumit (M)", + "unmute": "Zrušit ztlumení (M)", + "playback-speed": "Rychlost přehrávání", + "loop": "Cyklus", + "disable-loop": "Zakázat cyklus", + "rotate": "Otočit", + "picture-in-picture": "Obraz v obraze", + "exit-picture-in-picture": "Ukončit obraz v obraze", + "fullscreen": "Celá obrazovka (F)", + "exit-fullscreen": "Ukončit celou obrazovku", + "unsupported-format": "Náhled médií není dostupný pro tento formát souboru:\n {{mime}}", + "zoom-to-fit": "Přiblížit do šířky", + "zoom-reset": "Obnovit přiblížení do šířky" + }, + "protected_session": { + "enter_password_instruction": "Zobrazení chráněné poznámky vyžadující zadání hesla:", + "start_session_button": "Spustit chráněnou relaci", + "started": "Chráněná relace byla spuštěna.", + "wrong_password": "Nesprávné heslo.", + "protecting-finished-successfully": "Ochrana proběhla úspěšně.", + "unprotecting-finished-successfully": "Ochrana byla úspěšně zrušena.", + "protecting-in-progress": "Probíhá ochrana: {{count}}", + "unprotecting-in-progress-count": "Probíhá odchrana: {{count}}", + "protecting-title": "Stav ochrany", + "unprotecting-title": "Stav odchrany" + }, + "relation_map": { + "remove_note": "Odstranit poznámku", + "edit_title": "Upravit název", + "rename_note": "Přejmenovat poznámku", + "enter_new_title": "Zadejte nový název poznámky:", + "remove_relation": "Odstranit vazbu", + "confirm_remove_relation": "Jste si jisti, že chcete odstranit vazbu?", + "specify_new_relation_name": "Zadejte nový název vazby (povolené znaky: alfanumerické, dvojtečka a podtržítko):", + "connection_exists": "Připojení '{{name}}' mezi těmito poznámkami již existuje.", + "start_dragging_relations": "Začněte táhnout vazby odsud a přetáhněte je na jinou poznámku.", + "note_not_found": "Poznámka {{noteId}} nebyla nalezena!", + "cannot_match_transform": "Nelze porovnat transformaci: {{transform}}", + "note_already_in_diagram": "Poznámka \"{{title}}\" je již v diagramu.", + "enter_title_of_new_note": "Zadejte název nové poznámky", + "default_new_note_title": "nová poznámka", + "click_on_canvas_to_place_new_note": "Klikněte na plátno pro umístění nové poznámky" + }, + "render": { + "setup_title": "Zobrazit vlastní HTML nebo Preact JSX uvnitř této poznámky", + "setup_create_sample_preact": "Vytvořit ukázkovou poznámku s Preact", + "setup_create_sample_html": "Vytvořit ukázkovou poznámku s HTML", + "setup_sample_created": "Jako dceřiná poznámka byla vytvořena ukázková poznámka.", + "disabled_description": "Tato poznámka pro vykreslení pochází z externího zdroje. Abychom vás ochránili před škodlivým obsahem, není ve výchozím nastavení povolena. Ujistěte se, že zdroji důvěřujete, než ji povolíte.", + "disabled_button_enable": "Povolit poznámku pro vykreslení" + }, + "web_view_setup": { + "title": "Vytvořte živý pohled na webovou stránku přímo v Trilium", + "url_placeholder": "Zadejte nebo vložte webovou adresu, například https://triliumnotes.org", + "create_button": "Vytvořit Webový Pohled", + "invalid_url_title": "Neplatná adresa", + "invalid_url_message": "Vložte platnou webovou adresu, například https://triliumnotes.org.", + "disabled_description": "Tento webový pohled byl importován z externího zdroje. Abychom vás ochránili před phishingem nebo škodlivým obsahem, nenačítá se automaticky. Můžete jej povolit, pokud zdroji důvěřujete.", + "disabled_button_enable": "Povolit webový pohled" + }, + "backend_log": { + "refresh": "Obnovit" + }, + "consistency_checks": { + "title": "Kontroly konzistence", + "find_and_fix_button": "Najděte a opravte problémy s konzistencí", + "finding_and_fixing_message": "Hledání a oprava problémů s konzistencí...", + "issues_fixed_message": "Všechny nalezené problémy s konzistencí byly nyní opraveny." + }, + "database_anonymization": { + "title": "Anonymizace Databáze", + "full_anonymization": "Úplná Anonymizace", + "full_anonymization_description": "Tato akce vytvoří novou kopii databáze a anonymizuje ji (odstraní veškerý obsah poznámek a ponechá pouze strukturu a některá nesenzitivní metadata) pro sdílení online pro účely ladění bez obav z úniku vašich osobních údajů.", + "save_fully_anonymized_database": "Uložit plně anonymizovanou databázi", + "light_anonymization": "Částečná Anonymizace", + "light_anonymization_description": "Tato akce vytvoří novou kopii databáze a provede v ní částečnou anonymizaci — konkrétně budou odstraněny pouze obsahy všech poznámek, zatímco názvy a atributy zůstanou zachovány. Zachovány zůstanou také vlastní skripty poznámek v JS pro frontend i backend a vlastní widgety. To poskytuje více kontextu pro ladění problémů.", + "choose_anonymization": "Můžete se sami rozhodnout, zda chcete poskytnout plně nebo částečně anonymizovanou databázi. I plně anonymizovaná databáze je velmi užitečná, ale v některých případech může částečně anonymizovaná databáze urychlit proces identifikace a opravy chyb.", + "save_lightly_anonymized_database": "Uložit částečně anonymizovanou databázi", + "existing_anonymized_databases": "Existující anonymizované databáze", + "creating_fully_anonymized_database": "Vytváření plně anonymizované databáze...", + "creating_lightly_anonymized_database": "Vytváření částečně anonymizované databáze...", + "error_creating_anonymized_database": "Nepodařilo se vytvořit anonymizovanou databázi, podrobnosti najdete v protokolech backendu", + "successfully_created_fully_anonymized_database": "Vytvořena plně anonymizovaná databáze v {{anonymizedFilePath}}", + "successfully_created_lightly_anonymized_database": "Vytvořena částečně anonymizovaná databáze v {{anonymizedFilePath}}", + "no_anonymized_database_yet": "Zatím žádná anonymizovaná databáze." + }, + "database_integrity_check": { + "title": "Kontrola integrity databáze", + "description": "Toto zkontroluje, zda databáze není poškozena na úrovni SQLite. Může to chvíli trvat v závislosti na velikosti databáze.", + "check_button": "Zkontrolovat integritu databáze", + "checking_integrity": "Probíhá kontrola integrity databáze...", + "integrity_check_succeeded": "Kontrola integrity proběhla úspěšně - nebyly nalezeny žádné problémy.", + "integrity_check_failed": "Kontrola integrity selhala: {{results}}" + }, + "sync": { + "title": "Synchronizace", + "force_full_sync_button": "Vynutit úplnou synchronizaci", + "fill_entity_changes_button": "Naplnit záznamy změn entit", + "full_sync_triggered": "Spuštěna úplná synchronizace", + "filling_entity_changes": "Probíhá naplňování řádků změn entit...", + "sync_rows_filled_successfully": "Řádky synchronizace byly úspěšně naplněny", + "finished-successfully": "Synchronizace proběhla úspěšně.", + "failed": "Synchronizace selhala: {{message}}" + }, + "vacuum_database": { + "title": "Vyčistit databázi (Vacuum)", + "description": "Tímto se provede rekonstrukce databáze, což obvykle povede k menšímu souboru databáze. Žádná data nebudou ve skutečnosti změněna.", + "button_text": "Vyčistit databázi", + "vacuuming_database": "Probíhá čištění databáze...", + "database_vacuumed": "Databáze byla vyčištěna" + }, + "experimental_features": { + "title": "Experimentální Nastavení", + "disclaimer": "Tato nastavení jsou experimentální a mohou způsobit nestabilitu. Používejte s opatrností.", + "new_layout_name": "Nové Rozložení", + "new_layout_description": "Vyzkoušejte nové rozložení pro modernější vzhled a lepší použitelnost. Podléhá velkým změnám v nadcházejících verzích.", + "llm_name": "AI / LLM Chat", + "llm_description": "Povolte postranní panel AI chatu a poznámky LLM chatu poháněné velkými jazykovými modely." + }, + "fonts": { + "theme_defined": "Definované téma", + "fonts": "Písma", + "main_font": "Hlavní písmo", + "font_family": "Rodina písma", + "size": "Velikost", + "note_tree_font": "Font stromu poznámek", + "note_detail_font": "Font detailu poznámky", + "monospace_font": "Monospace (kód) Font", + "note_tree_and_detail_font_sizing": "Upozorňujeme, že velikost fontu stromu a detailu je relativní k hlavnímu nastavení velikosti fontu.", + "not_all_fonts_available": "Ne všechny uvedené fonty nemusí být dostupné ve vašem systému.", + "apply_font_changes": "Pro použití změn fontu klikněte na", + "reload_frontend": "obnovení frontendu", + "generic-fonts": "Obecné fonty", + "sans-serif-system-fonts": "Systémové sans-serif fonty", + "serif-system-fonts": "Systémové serif fonty", + "monospace-system-fonts": "Systémové monospace fonty", + "handwriting-system-fonts": "Systémové fonty pro psaní rukou", + "serif": "Serif", + "sans-serif": "Sans Serif", + "monospace": "Monospace", + "system-default": "Výchozí systémové nastavení" + }, + "max_content_width": { + "title": "Šířka obsahu", + "default_description": "Trilium ve výchozím nastavení omezuje maximální šířku obsahu pro zlepšení čitelnosti na maximalizovaných obrazovkách na širokých monitorech.", + "max_width_label": "Maximální šířka obsahu", + "max_width_unit": "pixelů", + "centerContent": "Udržovat obsah centrováný" + }, + "native_title_bar": { + "title": "Nativní panel titulku (vyžaduje restart aplikace)", + "enabled": "zapnuto", + "disabled": "vypnuto" + }, + "ribbon": { + "widgets": "Widgety pásu karet", + "promoted_attributes_message": "Záložka „Propagované Atributy“ se automaticky otevře, pokud jsou v poznámce přítomny povýšené atributy", + "edited_notes_message": "Záložka Upravené poznámky na pásu karet se automaticky otevře u denních poznámek" + }, + "theme": { + "title": "Vzhled aplikace", + "theme_label": "Vzhled", + "override_theme_fonts_label": "Přepsat písma vzhledu", + "auto_theme": "Starší (Sledovat barevné schéma systému)", + "light_theme": "Starší (Světlé)", + "dark_theme": "Starší (Tmavé)", + "triliumnext": "Trilium (Sledovat barevné schéma systému)", + "triliumnext-light": "Trilium (Světlé)", + "triliumnext-dark": "Trilium (Tmavé)", + "layout": "Rozložení", + "layout-vertical-title": "Vertikální", + "layout-horizontal-title": "Horizontální", + "layout-vertical-description": "panel spouštěčů je vlevo (výchozí nastavení)", + "layout-horizontal-description": "panel spouštěčů je pod záložkou, záložka je nyní celá šířka." + }, + "ui-performance": { + "title": "Výkon", + "enable-motion": "Povolit přechody a animace", + "enable-shadows": "Povolit stíny", + "enable-backdrop-effects": "Povolit efekty pozadí pro nabídky, vyskakovací okna a panely", + "enable-smooth-scroll": "Povolit plynulé rolování", + "app-restart-required": "(restart aplikace je nutný pro projev změny)" + }, + "zoom_factor": { + "title": "Faktor zoomu (pouze desktop verze)", + "description": "Zoom lze ovládat i pomocí klávesových zkratek CTRL+- a CTRL+=." + }, + "code_auto_read_only_size": { + "title": "Automatická velikost pro režim Pouze pro čtení", + "description": "Automatická velikost poznámky pro režim Pouze pro čtení určuje velikost, po které se poznámky zobrazí v režimu Pouze pro čtení (z důvodu výkonu).", + "label": "Automatická velikost pro režim Pouze pro čtení (kódové poznámky)", + "unit": "znaků" + }, + "code-editor-options": { + "title": "Editor" + }, + "code_mime_types": { + "title": "Dostupné MIME typy v rozbalovací nabídce", + "tooltip_syntax_highlighting": "Zvýrazňování syntaxe", + "tooltip_code_block_syntax": "Kódové bloky v Textových poznámkách", + "tooltip_code_note_syntax": "Kódové poznámky" + }, + "vim_key_bindings": { + "use_vim_keybindings_in_code_notes": "Klávesové zkratky Vim", + "enable_vim_keybindings": "Povolit klávesové zkratky Vim v kódových poznámkách (bez ex módu)" + }, + "wrap_lines": { + "wrap_lines_in_code_notes": "Zabalit řádky v kódových poznámkách", + "enable_line_wrap": "Povolit zalomení řádků (změna může vyžadovat obnovení frontendu, aby se projevila)" + }, + "images": { + "images_section_title": "Obrázky", + "download_images_automatically": "Automaticky stahovat obrázky", + "download_images_description": "Automaticky stahovat obrázky odkazované v vloženém HTML, aby byly dostupné offline.", + "enable_image_compression": "Komprese obrázků", + "enable_image_compression_description": "Komprimovat a změnit velikost obrázků při nahrávání nebo vkládání.", + "max_image_dimensions": "Maximální rozměry obrázku", + "max_image_dimensions_description": "Obrázky překračující tuto velikost budou automaticky změněny.", + "max_image_dimensions_unit": "pixelů", + "jpeg_quality": "Kvalita JPEG", + "jpeg_quality_description": "Doporučený rozsah je 50–85. Nižší hodnoty snižují velikost souboru, vyšší hodnoty zachovávají detaily.", + "ocr_section_title": "Extrakce textu (OCR)", + "ocr_related_content_languages": "Jazyky obsahu (používané pro extrakci textu)", + "ocr_auto_process": "Automaticky zpracovávat nové soubory", + "ocr_auto_process_description": "Automaticky extrahovat text z nově nahraných nebo vložených souborů.", + "ocr_min_confidence": "Minimální spolehlivost", + "ocr_confidence_description": "Extrahovat pouze text nad touto hranicí spolehlivosti. Nižší hodnoty zahrnují více textu, ale mohou být méně přesné.", + "batch_ocr_title": "Zpracovat existující soubory", + "batch_ocr_description": "Extrahovat text ze všech existujících obrázků, PDF a Office dokumentů ve vašich poznámkách. To může trvat nějaký čas v závislosti na počtu souborů.", + "batch_ocr_start": "Spustit dávkové zpracování", + "batch_ocr_starting": "Spuštění dávkového zpracování...", + "batch_ocr_progress": "Zpracovávám {{processed}} z {{total}} souborů...", + "batch_ocr_completed": "Dávkové zpracování dokončeno! Zpracováno {{processed}} souborů.", + "batch_ocr_error": "Chyba během dávkového zpracování: {{error}}" + }, + "attachment_erasure_timeout": { + "attachment_erasure_timeout": "Časový limit pro vymazání příloh", + "attachment_auto_deletion_description": "Přílohy jsou automaticky smazány (a vymazány), pokud nejsou po definovaném časovém limitu odkazovány jejich poznámkách.", + "erase_attachments_after": "Vymazat nepoužité přílohy po:", + "manual_erasing_description": "Můžete také spustit vymazání ručně (bez ohledu na výše definovaný časový limit):", + "erase_unused_attachments_now": "Vymazat nepoužité přílohy nyní", + "unused_attachments_erased": "Nepoužívané přílohy byly vymazány." + }, + "network_connections": { + "network_connections_title": "Síťová připojení", + "check_for_updates": "Automaticky kontrolovat aktualizace" + }, + "note_erasure_timeout": { + "note_erasure_timeout_title": "Časový limit pro vymazání Poznámky", + "note_erasure_description": "Odstraněné poznámky (a atributy, revize...) jsou zpočátku pouze označeny jako odstraněné a lze je obnovit v dialogovém okně „Poslední poznámky“. Po uplynutí určité doby jsou odstraněné poznámky „vymazány“, což znamená, že jejich obsah již nelze obnovit. Toto nastavení vám umožňuje určit dobu, která uplyne mezi odstraněním a vymazáním poznámky.", + "erase_notes_after": "Vymazat Poznámky po:", + "manual_erasing_description": "Můžete také spustit vymazání ručně (bez ohledu na výše uvedený časový limit):", + "erase_deleted_notes_now": "Vymazat smazané Poznámky nyní", + "deleted_notes_erased": "Smazané Poznámky byly vymazány." + }, + "revisions_snapshot_interval": { + "note_revisions_snapshot_interval_title": "Interval snímků revizí Poznámky", + "note_revisions_snapshot_description": "Interval snímků revizí Poznámky je doba po které bude vytvořen nový snímek revize Poznámky. Více informací naleznete v wiki.", + "snapshot_time_interval_label": "Časový interval snímků revizí Poznámky:" + }, + "revisions_snapshot_limit": { + "note_revisions_snapshot_limit_title": "Limit snímků revizí Poznámky", + "note_revisions_snapshot_limit_description": "Limit počtu snímků revizí Poznámky se týká maximálního počtu revizí, které lze uložit pro každou Poznámku. Hodnota -1 znamená žádný limit, 0 znamená smazat všechny revize. Můžete nastavit maximální počet revizí pro jednu Poznámku pomocí štítku #versioningLimit.", + "snapshot_number_limit_label": "Limit počtu snímků revizí Poznámky:", + "snapshot_number_limit_unit": "snímky", + "erase_excess_revision_snapshots": "Vymazat nadbytečné snímky revizí nyní", + "erase_excess_revision_snapshots_prompt": "Nadbytečné snímky revizí byly vymazány." + }, + "search_engine": { + "title": "Vyhledávač", + "custom_search_engine_info": "Vlastní vyhledávač vyžaduje nastavení jak názvu, tak URL. Pokud některý z nich není nastaven, bude použit DuckDuckGo jako výchozí vyhledávač.", + "predefined_templates_label": "Předdefinované šablony vyhledávačů", + "bing": "Bing", + "baidu": "Baidu", + "duckduckgo": "DuckDuckGo", + "google": "Google", + "custom_name_label": "Název vlastního vyhledávače", + "custom_name_placeholder": "Přizpůsobit název vyhledávače", + "custom_url_label": "URL vlastního vyhledávače by měl obsahovat {keyword} jako zástupný symbol pro vyhledávací výraz.", + "custom_url_placeholder": "Přizpůsobit URL vyhledávače", + "save_button": "Uložit" + }, + "tray": { + "title": "Systémová informační oblast", + "enable_tray": "Povolit informační oblast (pro zavedení této změny je nutné Trilium restartovat)" + }, + "heading_style": { + "title": "Styl nadpisu", + "plain": "Prostý", + "underline": "Podtržení", + "markdown": "Ve stylu Markdown" + }, + "highlights_list": { + "title": "Seznam zvýraznění", + "description": "V pravém panelu můžete upravit seznam zvýraznění:", + "bold": "Tučné písmo", + "italic": "Kurzíva", + "underline": "Podtržený text", + "color": "Barevný text", + "bg_color": "Text s barvou pozadí", + "visibility_title": "Viditelnost seznamu zvýraznění", + "visibility_description": "Widget zvýraznění můžete pro jednotlivé poznámky skrýt přidáním štítku #hideHighlightWidget.", + "shortcut_info": "Můžete nakonfigurovat klávesovou zkratku pro rychlé přepínání pravého panelu (včetně zvýraznění) v Nastavení -> Zkratky (název 'toggleRightPane')." + }, + "table_of_contents": { + "title": "Obsah", + "description": "Obsah se zobrazí v textových Poznámkách, pokud Poznámka obsahuje více než definovaný počet nadpisů. Můžete si přizpůsobit tento počet:", + "unit": "nadpisů", + "disable_info": "Můžete také použít tuto možnost pro efektivní vypnutí TOC nastavením velmi vysokého čísla.", + "shortcut_info": "Můžete nakonfigurovat klávesovou zkratku pro rychlé přepínání pravého panelu (včetně TOC) v Nastavení -> Zkratky (název 'toggleRightPane')." + }, + "text_auto_read_only_size": { + "title": "Automatická velikost pro Pouze pro čtení", + "description": "Automatická velikost Poznámky pro Pouze pro čtení je velikost, po které se Poznámky zobrazí v režimu Pouze pro čtení (z důvodu výkonu).", + "label": "Automatická velikost pro Pouze pro čtení (textové Poznámky)", + "unit": "znaků" + }, + "custom_date_time_format": { + "title": "Vlastní formát data/času", + "description": "Přizpůsobte formát data a času vloženého pomocí nebo panelu nástrojů. Podívejte se na dokumentaci Day.js pro dostupné tokeny formátu.", + "format_string": "Řetězec formátu:", + "formatted_time": "Formátované datum/čas:" + }, + "i18n": { + "title": "Lokalizace", + "language": "Čeština", + "first-day-of-the-week": "První den v týdnu", + "monday": "Pondělí", + "tuesday": "Úterý", + "wednesday": "Středa", + "thursday": "Čtvrtek", + "friday": "Pátek", + "saturday": "Sobota", + "sunday": "Neděle", + "first-week-of-the-year": "První týden v roce", + "first-week-contains-first-day": "První týden obsahuje první den v roce", + "first-week-contains-first-thursday": "První týden obsahuje první čtvrtek v roce", + "first-week-has-minimum-days": "První týden má minimální počet dní", + "min-days-in-first-week": "Minimální počet dní v prvním týdnu", + "first-week-info": "První týden obsahuje první čtvrtek v roce je založen na ISO 8601 standardu.", + "first-week-warning": "Změna možností prvního týdne může způsobit duplikaci se stávajícími Týdenními Poznámkami a stávající Týdenní Poznámky nebudou odpovídajícím způsobem aktualizovány.", + "formatting-locale": "Formát data & čísel", + "formatting-locale-auto": "Na základě jazyka aplikace" + }, + "backup": { + "automatic_backup": "Automatické zálohování", + "automatic_backup_description": "Trilium může automaticky zálohovat databázi:", + "enable_daily_backup": "Povolit denní zálohování", + "enable_weekly_backup": "Povolit týdenní zálohování", + "enable_monthly_backup": "Povolit měsíční zálohování", + "backup_recommendation": "Doporučuje se ponechat zálohování zapnuté, ale to může zpomalit spuštění aplikace s velkými databázemi a/nebo pomalými úložnými zařízeními.", + "backup_now": "Zálohovat nyní", + "backup_database_now": "Zálohovat databázi nyní", + "existing_backups": "Existující zálohy", + "date-and-time": "Datum & čas", + "path": "Cesta", + "database_backed_up_to": "Databáze byla zálohována do {{backupFilePath}}", + "no_backup_yet": "Zatím neexistuje žádná záloha" + }, + "etapi": { + "title": "ETAPI", + "description": "ETAPI je REST API používané pro programatický přístup k instanci Trilium bez uživatelského rozhraní.", + "create_token": "Vytvořit nový ETAPI token", + "existing_tokens": "Existující tokeny", + "no_tokens_yet": "Zatím neexistují žádné tokeny. Klikněte na tlačítko výše a vytvořte jeden.", + "token_name": "Název tokenu", + "created": "Vytvořeno", + "actions": "Akce", + "new_token_title": "Nový ETAPI token", + "new_token_message": "Zadejte název nového tokenu", + "default_token_name": "nový token", + "error_empty_name": "Název tokenu nemůže být prázdný", + "token_created_title": "ETAPI token vytvořen", + "token_created_message": "Zkopírujte vytvořený token do schránky. Trilium token ukládá hashovaný a toto je poslední možnost, jak jej uvidíte.", + "rename_token": "Přejmenovat tento token", + "delete_token": "Smazat / deaktivovat tento token", + "rename_token_title": "Přejmenovat token", + "rename_token_message": "Zadejte nový název tokenu", + "delete_token_confirmation": "Jste si jisti, že chcete smazat ETAPI token \"{{name}}\"?" + }, + "options_widget": { + "options_status": "Stav Nastavení", + "options_change_saved": "Změny v Nastavení byly uloženy." + }, + "password": { + "heading": "Heslo", + "alert_message": "Dávejte pozor, abyste si zapamatovali své nové heslo. Heslo se používá pro přihlášení do webového rozhraní a pro šifrování chráněných Poznámek. Pokud heslo zapomenete, všechny vaše chráněné Poznámky budou navždy ztraceny.", + "reset_link": "Klikněte zde pro jeho resetování.", + "old_password": "Staré heslo", + "new_password": "Nové heslo", + "new_password_confirmation": "Potvrzení nového hesla", + "change_password": "Změnit heslo", + "protected_session_timeout": "Časový limit pro Chráněná relace", + "protected_session_timeout_description": "Časový limit chráněné relace je doba, po které se chráněná relace vymaže z paměti prohlížeče. Měří se od poslední interakce s chráněnými poznámkami. Viz", + "wiki": "wiki", + "for_more_info": "pro více informací.", + "protected_session_timeout_label": "Časový limit chráněné relace:", + "reset_confirmation": "Resetováním hesla navždy ztratíte přístup ke všem svým existujícím chráněným poznámkám. Opravdu chcete heslo resetovat?", + "reset_success_message": "Heslo bylo resetováno. Nastavte nové heslo", + "change_password_heading": "Změnit heslo", + "set_password_heading": "Nastavit heslo", + "set_password": "Nastavit heslo", + "password_mismatch": "Nová hesla se neshodují.", + "password_changed_success": "Heslo bylo změněno. Trilium se po stisknutí OK znovu načte." + }, + "multi_factor_authentication": { + "title": "Vícefaktorová autentizace", + "description": "Vícefaktorová autentizace (MFA) přidává další vrstvu zabezpečení k vašemu účtu. Místo pouhého zadání hesla pro přihlášení MFA vyžaduje, abyste poskytli jeden nebo více dalších důkazů pro ověření vaší identity. Tímto způsobem, i když se někdo dostane k vašemu heslu, nemůže se k vašemu účtu dostat bez druhého kusu informace. Je to jako přidání dalšího zámku ke dveřím, což ztěžuje vniknutí kohokoli jiného.

Postupujte podle pokynů níže a povolte MFA. Pokud to nenakonfigurujete správně, přihlášení se vrátí pouze k heslu.", + "mfa_enabled": "Povolit vícefaktorovou autentizaci", + "mfa_method": "Metoda MFA", + "electron_disabled": "Multifaktorová autentizace není v desktop verzi aktuálně podporována.", + "totp_title": "Časově založené jednorázové heslo (TOTP)", + "totp_description": "TOTP (Časově založené jednorázové heslo) je bezpečnostní funkce, která generuje jedinečný, dočasný kód, který se mění každých 30 sekund. Tento kód spolu s vaším heslem použijete k přihlášení do svého účtu, což ztěžuje přístup k němu pro kohokoli jiného.", + "totp_secret_title": "Generovat TOTP tajný klíč", + "totp_secret_generate": "Generovat TOTP tajný klíč", + "totp_secret_regenerate": "Regenerovat TOTP tajný klíč", + "no_totp_secret_warning": "Pro povolení TOTP je nejprve nutné vygenerovat TOTP tajný klíč.", + "totp_secret_description_warning": "Po vygenerování nového TOTP tajného klíče budete muset znovu přihlásit pomocí nového TOTP tajného klíče.", + "totp_secret_generated": "TOTP tajný klíč vygenerován", + "totp_secret_warning": "Uložte vygenerovaný tajný klíč na bezpečném místě. Nebude znovu zobrazen.", + "totp_secret_regenerate_confirm": "Jste si jisti, že chcete regenerovat TOTP tajný klíč? Tím se zneplatní předchozí TOTP tajný klíč a všechny existující záchranné kódy.", + "recovery_keys_title": "Záchranné klíče pro jednotné přihlašování", + "recovery_keys_description": "Záchranné klíče pro jednotné přihlašování se používají k přihlášení v případě, že nemáte přístup ke svým autentifikačním kódům.", + "recovery_keys_description_warning": "Záchranné klíče nebudou po opuštění stránky znovu zobrazeny, uchovejte je na bezpečném místě. Po použití záchranného klíče jej nelze znovu použít.", + "recovery_keys_error": "Chyba při generování záchranných kódů", + "recovery_keys_no_key_set": "Nebyly nastaveny žádné záchranné kódy", + "recovery_keys_generate": "Generovat záchranné kódy", + "recovery_keys_regenerate": "Regenerovat záchranné kódy", + "recovery_keys_used": "Použito: {{date}}", + "recovery_keys_unused": "Záchranný kód {{index}} nebyl použit", + "oauth_title": "OAuth/OpenID", + "oauth_description": "OpenID je standardizovaný způsob, jak se přihlásit na webové stránky pomocí účtu z jiné služby, jako je Google, pro ověření vaší identity. Výchozí vydavatel je Google, ale můžete jej změnit na jakéhokoli jiného ⟨OpenID provider⟩. Podrobnosti naleznete zde. Postupujte podle těchto instrukcí pro nastavení služby OpenID přes Google.", + "oauth_description_warning": "Pro povolení OAuth/OpenID musíte nastavit základní ⟨URL⟩ OAuth/OpenID, ID klienta a tajný klíč klienta v souboru config.ini a restartovat aplikaci. Pokud chcete nastavit z proměnných prostředí, nastavte TRILIUM_OAUTH_BASE_URL, TRILIUM_OAUTH_CLIENT_ID a TRILIUM_OAUTH_CLIENT_SECRET.", + "oauth_missing_vars": "Chybějící nastavení: {{-variables}}", + "oauth_user_account": "Uživatelský účet: ", + "oauth_user_email": "Uživatelský e-mail: ", + "oauth_user_not_logged_in": "Není přihlášen!" + }, + "shortcuts": { + "keyboard_shortcuts": "Klávesové zkratky", + "multiple_shortcuts": "Více zkratek pro stejnou akci lze oddělit čárkou.", + "electron_documentation": "Dostupné modifikátory a kódy kláves naleznete v dokumentaci Electronu.", + "type_text_to_filter": "Napište text pro filtrování zkratek...", + "action_name": "Název akce", + "shortcuts": "Zkratky", + "default_shortcuts": "Výchozí zkratky", + "description": "Popis", + "reload_app": "Načtěte aplikaci pro použití změn", + "set_all_to_default": "Nastavte všechny zkratky na výchozí", + "confirm_reset": "Opravdu chcete resetovat všechny klávesové zkratky na výchozí?", + "no_results": "Nebyly nalezeny žádné zkratky odpovídající '{{filter}}'" + }, + "spellcheck": { + "title": "Kontrola pravopisu", + "description": "Tato nastavení platí pouze pro ⟨desktop⟩ verze, prohlížeče budou používat vlastní nativní kontrolu pravopisu.", + "enable": "Povolit kontrolu pravopisu", + "language_code_label": "Kód jazyka(ů)", + "restart-required": "Změny v nastavení kontroly pravopisu se projeví po restartu aplikace." + }, + "sync_2": { + "config_title": "Konfigurace Synchronizace", + "server_address": "Adresa instance serveru", + "timeout": "Časový limit synchronizace", + "proxy_label": "Proxy server pro synchronizaci (volitelné)", + "note": "Poznámka", + "note_description": "Pokud ponecháte nastavení proxy prázdné, bude použit systémový proxy (platí pouze pro desktop/electron build).", + "special_value_description": "Další speciální hodnota je noproxy, která vynutí ignorování i systémového proxy a respektuje NODE_TLS_REJECT_UNAUTHORIZED.", + "save": "Uložit", + "help": "Nápověda", + "test_title": "Test Synchronizace", + "test_description": "Tím se otestuje připojení a handshake se serverem synchronizace. Pokud server synchronizace není inicializován, nastaví se pro synchronizaci s lokálním dokumentem.", + "test_button": "Test synchronizace", + "handshake_failed": "Selhání handshake se serverem pro synchronizaci, chyba: {{message}}" + }, + "api_log": { + "close": "Zavřít" + }, + "attachment_detail_2": { + "will_be_deleted_in": "Tato příloha bude automaticky smazána za {{time}}", + "will_be_deleted_soon": "Tato příloha bude brzy automaticky smazána", + "deletion_reason": ", protože příloha není propojena s obsahem poznámky. Aby se smazání zabránilo, vložte odkaz na přílohu zpět do obsahu nebo převeďte přílohu na poznámku.", + "role_and_size": "Role: {{role}}, velikost: {{size}}, MIME: {{- mimeType}}", + "link_copied": "Odkaz na přílohu byl zkopírován do schránky.", + "unrecognized_role": "Nerozpoznaná role přílohy '{{role}}'." + }, + "bookmark_switch": { + "bookmark": "Záložka (oblíbená)", + "bookmark_this_note": "Přidejte tuto poznámku do záložek na levém panelu", + "remove_bookmark": "Odebrat záložku" + }, + "editability_select": { + "auto": "Automaticky", + "read_only": "Pouze pro čtení", + "always_editable": "Vždy upravitelná", + "note_is_editable": "Poznámka je upravitelná, pokud není příliš dlouhá.", + "note_is_read_only": "Poznámka je pouze pro čtení, ale lze ji upravit kliknutím na tlačítko.", + "note_is_always_editable": "Poznámka je vždy editovatelná, bez ohledu na její délku." + }, + "note-map": { + "button-link-map": "Mapa odkazů", + "button-tree-map": "Mapa stromu" + }, + "tree-context-menu": { + "open-in-a-new-tab": "Otevřít v nové záložce", + "open-in-a-new-split": "Otevřít v novém rozdělení", + "open-in-a-new-window": "Otevřít v novém okně", + "insert-note-after": "Vložit poznámku za", + "insert-child-note": "Vložit dceřinou poznámku", + "archive": "Archivovat", + "unarchive": "Obnovit z archivu", + "delete": "Smazat", + "search-in-subtree": "Hledat v podstromu", + "hoist-note": "Přesunout poznámku nahoru", + "unhoist-note": "Přesunout poznámku dolů", + "edit-branch-prefix": "Upravit předponu větve", + "advanced": "Pokročilé", + "expand-subtree": "Rozbalit podstrom", + "collapse-subtree": "Sbalit podstrom", + "hide-subtree": "Skrýt podstrom", + "show-subtree": "Zobrazit podstrom", + "sort-by": "Seřadit podle...", + "recent-changes-in-subtree": "Nedávné změny v podstromu", + "convert-to-attachment": "Převést na přílohu", + "copy-note-path-to-clipboard": "Kopírovat cestu poznámky do schránky", + "protect-subtree": "Chránit podstrom", + "unprotect-subtree": "Zrušit ochranu podstromu", + "copy-clone": "Kopírovat / klonovat", + "clone-to": "Klonovat do...", + "cut": "Vyjmout", + "move-to": "Přesunout do...", + "paste-into": "Vložit do", + "paste-after": "Vložit za", + "duplicate": "Duplikovat", + "export": "Export", + "import-into-note": "Importovat do Poznámky", + "apply-bulk-actions": "Použít hromadné akce", + "converted-to-attachments": "{{count}} Poznámek bylo převedeno na Přílohy.", + "convert-to-attachment-confirm": "Jste si jisti, že chcete převést vybrané Poznámky na Přílohy jejich nadřazených Poznámek? Tato operace se vztahuje pouze na Poznámky typu Obrázek, ostatní Poznámky budou přeskočeny.", + "open-in-popup": "Rychlá úprava" + }, + "shared_info": { + "shared_publicly": "Tato Poznámka je veřejně Sdílena na {{- link}}.", + "shared_locally": "Tato Poznámka je lokálně Sdílena na {{- link}}.", + "help_link": "Pro pomoc navštivte wiki." + }, + "read-only-info": { + "read-only-note": "Zobrazujete Poznámku pouze pro čtení.", + "auto-read-only-note": "Tato Poznámka je zobrazena v režimu Pouze pro čtení pro rychlejší načítání.", + "edit-note": "Upravit Poznámku" + }, + "note_types": { + "text": "Text", + "code": "Kód", + "saved-search": "Uložené vyhledávání", + "relation-map": "Mapa Vazeb", + "note-map": "Mapa Poznámek", + "render-note": "Poznámka pro vykreslení", + "book": "Kolekce", + "mermaid-diagram": "Mermaid Diagram", + "canvas": "Plátno", + "web-view": "Webový pohled", + "mind-map": "Mentální mapa", + "file": "Soubor", + "image": "Obrázek", + "launcher": "Spouštěč", + "doc": "Dokument", + "widget": "Widget", + "confirm-change": "Nedoporučuje se měnit typ poznámky, pokud není prázdná. Chcete pokračovat?", + "geo-map": "Geomapa", + "beta-feature": "Beta", + "ai-chat": "AI Chat", + "llm-chat": "AI Chat", + "task-list": "Seznam úkolů", + "new-feature": "Nový", + "collections": "Kolekce", + "spreadsheet": "Tabulka" + }, + "protect_note": { + "toggle-on": "Zabezpečit poznámku", + "toggle-off": "Zrušit zabezpečení poznámky", + "toggle-on-hint": "Poznámka není zabezpečená, klikněte pro její zabezpečení", + "toggle-off-hint": "Poznámka je zabezpečená, klikněte pro zrušení zabezpečení" + }, + "llm_chat": { + "placeholder": "Napište zprávu...", + "send": "Odeslat", + "sending": "Odesílání...", + "empty_state": "Zahajte konverzaci napsáním zprávy níže.", + "searching_web": "Hledání na webu...", + "web_search": "Vyhledávání na webu", + "note_tools": "Přístup k Poznámce", + "sources": "Zdroje", + "sources_summary": "{{count}} zdrojů z {{sites}} webů", + "extended_thinking": "Rozšířené myšlení", + "legacy_models": "Starší modely", + "thinking": "Přemýšlím...", + "thought_process": "Myšlenkový proces", + "tool_calls": "{{count}} volání nástroje(ů)", + "input": "Vstup", + "result": "Výsledek", + "error": "Chyba", + "tool_error": "selhalo", + "total_tokens": "{{total}} tokenů", + "tokens_detail": "{{prompt}} prompt + {{completion}} completion", + "tokens_used": "{{prompt}} prompt + {{completion}} completion = {{total}} tokenů", + "tokens_used_with_cost": "{{prompt}} prompt + {{completion}} completion = {{total}} tokenů (~${{cost}})", + "tokens_used_with_model": "{{model}}: {{prompt}} prompt + {{completion}} completion = {{total}} tokenů", + "tokens_used_with_model_and_cost": "{{model}}: {{prompt}} prompt + {{completion}} completion = {{total}} tokenů (~${{cost}})", + "tokens": "tokenů", + "context_used": "{{percentage}}% použito", + "note_context_enabled": "Kliknutím zakažte kontext poznámky: {{title}}", + "note_context_disabled": "Kliknutím zahrňte aktuální Poznámku do kontextu", + "no_provider_message": "Nebyl nakonfigurován žádný AI poskytovatel. Přidejte jeden pro zahájení chatu.", + "add_provider": "Přidat AI Poskytovatele" + }, + "sidebar_chat": { + "title": "AI Chat", + "launcher_title": "Otevřít AI Chat", + "new_chat": "Zahájit nový chat", + "save_chat": "Uložit chat do poznámek", + "empty_state": "Zahájit konverzaci", + "history": "Historie chatu", + "recent_chats": "Nedávné chaty", + "no_chats": "Žádné předchozí chaty" + }, + "shared_switch": { + "shared": "Sdíleno", + "toggle-on-title": "Sdílet poznámku", + "toggle-off-title": "Zrušit sdílení poznámky", + "shared-branch": "Tato poznámka existuje pouze jako sdílená poznámka, zrušení sdílení by ji smazalo. Chcete pokračovat a tímto poznámku smazat?", + "inherited": "Poznámku nelze zde zrušit sdílení, protože je sdílena dědičně z nadřazené poznámky." + }, + "template_switch": { + "template": "Šablona", + "toggle-on-hint": "Udělat z poznámky šablonu", + "toggle-off-hint": "Odstranit poznámku jako šablonu" + }, + "open-help-page": "Otevřít stránku nápovědy", + "find": { + "case_sensitive": "Rozlišovat malá a velká písmena", + "match_words": "Shoda slov", + "find_placeholder": "Najít v textu...", + "replace_placeholder": "Nahradit pomocí...", + "replace": "Nahradit", + "replace_all": "Nahradit vše" + }, + "highlights_list_2": { + "title": "Seznam zvýraznění", + "options": "Nastavení", + "modal_title": "Konfigurovat seznam zvýraznění", + "menu_configure": "Konfigurovat seznam zvýraznění...", + "no_highlights": "Nebyla nalezena žádná zvýraznění.", + "title_with_count_one": "{{count}} zvýraznění", + "title_with_count_few": "{{count}} zvýraznění", + "title_with_count_other": "{{count}} zvýraznění" + }, + "quick-search": { + "placeholder": "Rychlé hledání", + "searching": "Hledání...", + "no-results": "Nebyla nalezena žádná výsledná", + "more-results": "... a dalších {{number}} výsledků.", + "show-in-full-search": "Zobrazit v úplném vyhledávání" + }, + "note_tree": { + "collapse-title": "Sbalit strom poznámek", + "scroll-active-title": "Posunout k aktivní poznámce", + "tree-settings-title": "Nastavení stromu", + "hide-archived-notes": "Skrýt archivované poznámky", + "automatically-collapse-notes": "Automaticky sbalovat poznámky", + "automatically-collapse-notes-title": "Poznámky budou po období nečinnosti sbaleny, aby se strom nepřehltil.", + "save-changes": "Uložit a použít změny", + "auto-collapsing-notes-after-inactivity": "Automatické sbalování poznámek po nečinnosti...", + "saved-search-note-refreshed": "Uložené vyhledávání poznámky bylo obnoveno.", + "hoist-this-note-workspace": "Vyvýšit tuto poznámku (pracovní plocha)", + "refresh-saved-search-results": "Obnovit výsledky uloženého vyhledávání", + "create-child-note": "Vytvořit dceřinnou poznámku", + "unhoist": "Unhoist", + "toggle-sidebar": "Přepnout boční panel", + "dropping-not-allowed": "Do této polohy nelze poznámky přesouvat.", + "clone-indicator-tooltip": "Tato poznámka má {{- count}} rodičů: {{- parents}}", + "clone-indicator-tooltip-single": "Tato poznámka je klonována (1 další rodič: {{- parent}})", + "shared-indicator-tooltip": "Tato poznámka je sdílena veřejně", + "shared-indicator-tooltip-with-url": "Tato poznámka je sdílena veřejně na: {{- url}}", + "subtree-hidden-moved-title": "Přidáno do {{title}}", + "subtree-hidden-moved-description-collection": "Tato kolekce skrývá své dceřiné poznámky ve stromu.", + "subtree-hidden-moved-description-other": "Dceřiné poznámky jsou pro tuto poznámku skryty ve stromu.", + "subtree-hidden-tooltip_one": "{{count}} podřízená poznámka, která je ve stromu skrytá", + "subtree-hidden-tooltip_few": "{{count}} podřízené poznámky, které jsou ve stromu skryté", + "subtree-hidden-tooltip_other": "{{count}} podřízených poznámek, které jsou ve stromu skryté" + }, + "title_bar_buttons": { + "window-on-top": "Připítnout okno na horní část obrazovky" + }, + "note_detail": { + "could_not_find_typewidget": "Nebyl nalezen typeWidget pro typ '{{type}}'", + "printing": "Tisknutí probíhá...", + "printing_pdf": "Exportování do PDF probíhá...", + "print_report_title": "Vytisknout sestavu", + "print_report_error_title": "Tisk se nezdařil", + "print_report_stack_trace": "Stack trace", + "print_report_collection_details_button": "Zobrazit podrobnosti", + "print_report_collection_details_ignored_notes": "Ignorované poznámky", + "print_report_collection_content_one": "{{count}} poznámka ve sbírce nebyla možná vytisknout, protože není podporována nebo je chráněna.", + "print_report_collection_content_few": "{{count}} poznámky ve sbírce nebylo možné vytisknout, protože nejsou podporovány nebo jsou chráněny.", + "print_report_collection_content_other": "{{count}} poznámek ve sbírce nebylo možné vytisknout, protože nejsou podporovány nebo jsou chráněny." + }, + "note_title": { + "placeholder": "Zde napište název poznámky...", + "created_on": "Vytvořeno dne ", + "last_modified": "Upraveno dne ", + "note_type_switcher_label": "Přepnout z {{type}} na:", + "note_type_switcher_others": "Jiný typ poznámky", + "note_type_switcher_templates": "Šablona", + "note_type_switcher_collection": "Kolekce", + "edited_notes": "Poznámky upravené v tento den", + "promoted_attributes": "Propagované atributy" + }, + "search_result": { + "no_notes_found": "Pro zadané parametry hledání nebyly nalezeny žádné poznámky.", + "search_not_executed": "Hledání ještě nebylo provedeno.", + "search_now": "Hledat nyní" + }, + "spacer": { + "configure_launchbar": "Konfigurovat Launchbar" + }, + "sql_result": { + "not_executed": "Dotaz ještě nebyl proveden.", + "no_rows": "Pro tento dotaz nebyly vráceny žádné řádky", + "failed": "Provádění SQL dotazu selhalo", + "statement_result": "Výsledek příkazu", + "execute_now": "Spustit nyní" + }, + "sql_table_schemas": { + "tables": "Tabulky" + }, + "tab_row": { + "close_tab": "Zavřít záložku", + "add_new_tab": "Přidat novou záložku", + "close": "Zavřít", + "close_other_tabs": "Zavřít ostatní záložky", + "close_right_tabs": "Zavřít záložky vpravo", + "close_all_tabs": "Zavřít všechny záložky", + "reopen_last_tab": "Znovu otevřít poslední zavřenou záložku", + "move_tab_to_new_window": "Přesunout tuto záložku do nového okna", + "copy_tab_to_new_window": "Zkopírovat tuto záložku do nového okna", + "new_tab": "Nová záložka" + }, + "toc": { + "table_of_contents": "Obsah", + "options": "Nastavení", + "no_headings": "Žádné nadpisy." + }, + "watched_file_update_status": { + "file_last_modified": "Soubor byl naposledy upraven .", + "upload_modified_file": "Nahrát upravený soubor", + "ignore_this_change": "Ignorovat tuto změnu" + }, + "app_context": { + "please_wait_for_save": "Počkejte prosím několik sekund, dokud se dokončí ukládání, poté můžete zkusit znovu." + }, + "note_create": { + "duplicated": "Poznámka \"{{title}}\" byla duplikována." + }, + "image": { + "copied-to-clipboard": "Odkaz na obrázek byl zkopírován do schránky. Lze jej vložit do jakékoli textové poznámky.", + "cannot-copy": "Odkaz na obrázek nebylo možné zkopírovat do schránky." + }, + "clipboard": { + "cut": "Poznámka/poznámky byly vyříznuty do schránky.", + "copied": "Poznámka/poznámky byly zkopírovány do schránky.", + "copy_failed": "Nelze zkopírovat do schránky kvůli problémům s oprávněním.", + "copy_success": "Zkopírováno do schránky." + }, + "entrypoints": { + "note-revision-created": "Revize poznámky byla vytvořena.", + "note-executed": "Poznámka byla spuštěna.", + "sql-error": "Při provádění SQL dotazu došlo k chybě: {{message}}" + }, + "branches": { + "cannot-move-notes-here": "Poznámky sem nelze přesunout.", + "delete-status": "Stav mazání", + "delete-notes-in-progress": "Probíhá mazání poznámek: {{count}}", + "delete-finished-successfully": "Mazání proběhlo úspěšně.", + "undeleting-notes-in-progress": "Probíhá obnovování poznámek: {{count}}", + "undeleting-notes-finished-successfully": "Obnovení poznámek proběhlo úspěšně." + }, + "frontend_script_api": { + "async_warning": "Předáváte asynchronní funkci do `api.runOnBackend()`, což pravděpodobně nebude fungovat tak, jak jste zamýšleli.\\nBuď udělejte funkci synchronní (odstraněním klíčového slova `async`), nebo použijte `api.runAsyncOnBackendWithManualTransactionHandling()`.", + "sync_warning": "Předáváte synchronní funkci do `api.runAsyncOnBackendWithManualTransactionHandling()`,\\nzatímco byste pravděpodobně měli místo toho použít `api.runOnBackend()`." + }, + "ws": { + "sync-check-failed": "Kontrola synchronizace selhala!", + "consistency-checks-failed": "Kontroly konzistence selhaly! Podrobnosti najdete v protokolech.", + "encountered-error": "Došlo k chybě \"{{message}}\", podívejte se do konzole.", + "lost-websocket-connection-title": "Ztraceno připojení ke serveru", + "lost-websocket-connection-message": "Zkontrolujte konfiguraci svého reverzního proxy (např. nginx nebo Apache), zda jsou připojení WebSocket správně povolena a nejsou blokována." + }, + "hoisted_note": { + "confirm_unhoisting": "Požadovaná poznámka '{{requestedNote}}' se nachází mimo podstrom zúžené poznámky '{{hoistedNote}}' a pro k jejímu přístupu musíte provést zúžení zrušit. Chcete pokračovat v uvolnění zobrazení?" + }, + "launcher_context_menu": { + "reset_launcher_confirm": "Opravdu chcete resetovat \"{{title}}\"? Všechna data / nastavení v této poznámce (a jejích dceřiných poznámkách) budou ztracena a spouštěč se vrátí na své původní místo.", + "add-note-launcher": "Přidat spouštěč poznámky", + "add-script-launcher": "Přidat spouštěč skriptu", + "add-custom-widget": "Přidat vlastní widget", + "add-spacer": "Přidat oddělovač", + "delete": "Smazat ", + "reset": "Resetovat", + "move-to-visible-launchers": "Přesunout do viditelných spouštěčů", + "move-to-available-launchers": "Přesunout do dostupných spouštěčů", + "duplicate-launcher": "Duplikovat spouštěč " + }, + "highlighting": { + "title": "Bloky kódu", + "description": "Ovládá zvýrazňování syntaxe pro bloky kódu v textových poznámkách, poznámky kódu se tím nebudou dotýkat.", + "color-scheme": "Barevné schéma" + }, + "code_block": { + "word_wrapping": "Zalomování slov", + "theme_none": "Žádné zvýrazňování syntaxe", + "theme_group_light": "Světlé motivy", + "theme_group_dark": "Tmavé motivy", + "copy_title": "Kopírovat do schránky" + }, + "classic_editor_toolbar": { + "title": "Formátování" + }, + "editor": { + "title": "Editor" + }, + "editing": { + "editor_type": { + "label": "Lišta pro formátování", + "floating": { + "title": "Plovoucí", + "description": "nástroje pro úpravy se zobrazí u kurzoru;" + }, + "fixed": { + "title": "Fixní", + "description": "nástroje pro úpravu se zobrazují na záložce „Formátování“ v pásu karet." + }, + "multiline-toolbar": "Zobrazit panel nástrojů v několika řádcích, pokud se nevejde." + } + }, + "electron_context_menu": { + "add-term-to-dictionary": "Přidat „{{term}}“ do slovníku", + "cut": "Vyříznout", + "copy": "Kopírovat", + "copy-as-markdown": "Kopírovat jako Markdown", + "copy-link": "Kopírovat odkaz", + "paste": "Vložit", + "paste-as-plain-text": "Vložit jako prostý text", + "search_in_trilium": "Hledat „{{term}}“ v Trilium", + "search_online": "Hledat „{{term}}“ pomocí {{searchEngine}}" + }, + "image_context_menu": { + "copy_reference_to_clipboard": "Kopírovat referenci do schránky", + "copy_image_to_clipboard": "Kopírovat obrázek do schránky" + }, + "link_context_menu": { + "open_note_in_new_tab": "Otevřít poznámku v nové záložce", + "open_note_in_new_split": "Otevřít poznámku v novém rozdělení", + "open_note_in_other_split": "Otevřít poznámku v druhém rozdělení", + "open_note_in_new_window": "Otevřít poznámku v novém okně", + "open_note_in_popup": "Rychlá úprava" + }, + "electron_integration": { + "desktop-application": "Počítačová aplikace", + "native-title-bar": "Nativní názevku okna", + "native-title-bar-description": "Pro Windows a macOS vede vypnutí nativního názvu okna k kompaktnějšímu vzhledu aplikace. Na Linuxu lepší integraci s ostatní částí systému zajistí zapnutý nativní název okna.", + "background-effects": "Povolit efekty pozadí", + "background-effects-description": "Přidává rozmazané, stylové pozadí do oken aplikace, čímž vytváří hloubku a moderní vzhled. Musí být vypnutá funkce „Nativní název okna“.", + "restart-app-button": "Restartujte aplikaci pro zobrazení změn", + "zoom-factor": "Míra přiblížení" + }, + "note_autocomplete": { + "search-for": "Hledat \"{{term}}\"", + "create-note": "Vytvořit a propojit dceřinnou poznámku \"{{term}}\"", + "insert-external-link": "Vložit externí odkaz na \"{{term}}\"", + "clear-text-field": "Vymazat textové pole", + "show-recent-notes": "Zobrazit nedávné poznámky", + "full-text-search": "Vyhledávání v celém textu" + }, + "note_tooltip": { + "note-has-been-deleted": "Poznámka byla smazána.", + "quick-edit": "Rychlá úprava" + }, + "geo-map": { + "create-child-note-title": "Vytvořit novou dceřinou poznámku a přidat ji do mapy", + "create-child-note-text": "Přidat značku", + "create-child-note-instruction": "Kliknutím na mapu vytvoříte novou poznámku na daném místě nebo stisknutím klávesy Escape jej zavřete.", + "unable-to-load-map": "Nelze načíst mapu." + }, + "geo-map-context": { + "open-location": "Otevřít polohu", + "remove-from-map": "Odebrat z mapy", + "add-note": "Přidat značku na toto místo" + }, + "help-button": { + "title": "Otevřít příslušnou nápovědu" + }, + "duration": { + "seconds": "Sekundy", + "minutes": "Minuty", + "hours": "Hodiny", + "days": "Dny" + }, + "share": { + "title": "Nastavení sdílení", + "redirect_bare_domain": "Přesměrovat hlavní doménu na stránku sdílení", + "redirect_bare_domain_description": "Přesměrovat anonymní uživatele na stránku sdílení místo zobrazení přihlášení", + "show_login_link": "Zobrazit odkaz na přihlášení ve tématu sdílení", + "show_login_link_description": "Přidat odkaz na přihlášení do zápatí stránky sdílení", + "check_share_root": "Kontrola stavu kořenové poznámky sdílení", + "share_root_found": "Kořenová poznámka sdílení '{{noteTitle}}' je připravena", + "share_root_not_found": "Nebyla nalezena žádná poznámka se štítkem #shareRoot", + "share_root_not_shared": "Poznámka '{{noteTitle}}' má štítek #shareRoot, ale není sdílena" + }, + "time_selector": { + "invalid_input": "Zadaná hodnota času není platné číslo.", + "minimum_input": "Zadaná hodnota času musí být alespoň {{minimumSeconds}} sekund." + }, + "tasks": { + "due": { + "today": "Dnes", + "tomorrow": "Zítra", + "yesterday": "Včera" + } + }, + "content_widget": { + "unknown_widget": "Neznámý widget pro \"{{id}}\"." + }, + "note_language": { + "not_set": "Jazyk není nastaven", + "configure-languages": "Konfigurovat jazyky...", + "help-on-languages": "Nápověda k jazykům obsahu..." + }, + "content_language": { + "title": "Jazyky obsahu", + "description": "Vyberte jeden nebo více jazyků, které by měly být zobrazeny v výběru jazyka v části Základní vlastnosti poznámky typu pouze pro čtení nebo k editaci. To umožní funkce jako kontrola pravopisu, podpora písma zprava doleva a extrakce textu (OCR)." + }, + "switch_layout_button": { + "title_vertical": "Přesunout panel úprav na dolní část", + "title_horizontal": "Přesunout panel úpráv nalevo" + }, + "toggle_read_only_button": { + "unlock-editing": "Odemknout úpravy", + "lock-editing": "Uzamknout úpravy" + }, + "png_export_button": { + "button_title": "Exportovat diagram jako PNG" + }, + "svg": { + "export_to_png": "Diagram nebylo možné exportovat do PNG.", + "export_to_svg": "Diagram nebylo možné exportovat do SVG." + }, + "code_theme": { + "title": "Vzhled", + "word_wrapping": "Zalomování textu", + "color-scheme": "Barevné schéma" + }, + "cpu_arch_warning": { + "title": "Prosím stáhněte si verzi ARM64", + "message_macos": "TriliumNext momentálně běží pod překladem Rosetta 2, což znamená, že na Macu s Apple Silicon používáte verzi Intel (x64). To bude mít výrazný dopad na výkon a výdrž baterie.", + "message_windows": "TriliumNext momentálně běží v režimu emulace, což znamená, že na zařízení Windows pro ARM používáte verzi Intel (x64). To bude mít výrazný dopad na výkon a výdrž baterie.", + "recommendation": "Pro nejlepší zážitek si prosím stáhněte nativní verzi ARM64 aplikace TriliumNext z naší stránky s vydáními.", + "download_link": "Stáhnout nativní verzi", + "continue_anyway": "Pokračovat i tak", + "dont_show_again": "Toto varování již nezobrazovat" + }, + "editorfeatures": { + "title": "Funkce", + "emoji_completion_enabled": "Povolit automatické doplňování emoji", + "emoji_completion_description": "Pokud je tato funkce povolena, do textu lze snadno vkládat emoji napsáním symbolu `:`, následovaného názvem emoji.", + "note_completion_enabled": "Povolit automatické doplňování poznámek", + "note_completion_description": "Pokud je tato funkce povolena, lze vytvářet odkazy na poznámky napsáním symbolu `@`, následovaného názvem poznámky.", + "slash_commands_enabled": "Povolit lomítkové příkazy (slash commands)", + "slash_commands_description": "Pokud je tato funkce povolena, lze přepínat editační příkazy, jako je vkládání zalomení řádku nebo nadpisů, napsáním `/`." + }, + "table_view": { + "new-row": "Nový řádek", + "new-column": "Nový sloupec", + "sort-column-by": "Řadit podle \"{{title}}\"", + "sort-column-ascending": "Vzestupně", + "sort-column-descending": "Sestupně", + "sort-column-clear": "Vymazat řazení", + "hide-column": "Skrýt sloupec \"{{title}}\"", + "show-hide-columns": "Zobrazit/skrýt sloupce", + "row-insert-above": "Vložit řádek nad", + "row-insert-below": "Vložit řádek pod", + "row-insert-child": "Vložit dceřinnou poznámku", + "add-column-to-the-left": "Přidat sloupec vlevo", + "add-column-to-the-right": "Přidat sloupec vpravo", + "edit-column": "Upravit sloupec", + "delete_column_confirmation": "Opravdu chcete tento sloupec smazat? Odpovídající atribut bude odstraněn ze všech poznámek.", + "delete-column": "Odstranit sloupec", + "new-column-label": "Štítek", + "new-column-relation": "Vazba" + }, + "book_properties_config": { + "hide-weekends": "Skrýt víkendy", + "display-week-numbers": "Zobrazovat čísla týdnů", + "map-style": "Styl mapy", + "max-nesting-depth": "Maximální hloubka vnoření:", + "raster": "Raster", + "vector_light": "Vektor (Světlý)", + "vector_dark": "Vektor (Tmavý)", + "show-scale": "Zobrazit měřítko", + "show-labels": "Zobrazovat názvy značek" + }, + "table_context_menu": { + "delete_row": "Odstranit řádek" + }, + "board_view": { + "delete-note": "Odstranit poznámku...", + "remove-from-board": "Odebrat z tabule", + "archive-note": "Archivovat poznámku", + "unarchive-note": "Odarchivovat poznámku", + "move-to": "Přesunout do", + "insert-above": "Vložit nad", + "insert-below": "Vložit pod", + "delete-column": "Odstranit sloupec", + "delete-column-confirmation": "Opravdu chcete tento sloupec odstranit? Odstraněny budou i odpovídající atributy v poznámkách pod tímto sloupcem.", + "new-item": "Nová položka", + "new-item-placeholder": "Zadejte název poznámky...", + "add-column": "Přidat sloupec", + "add-column-placeholder": "Zadejte název sloupce...", + "edit-note-title": "Kliknutím upravíte název poznámky", + "edit-column-title": "Kliknutím upravíte název sloupce", + "column-already-exists": "Tento sloupec již na tabuli existuje." + }, + "presentation_view": { + "edit-slide": "Upravit tento snímek", + "start-presentation": "Spustit prezentaci", + "slide-overview": "Přepnout zobrazení přehledu snímků" + }, + "calendar_view": { + "delete_note": "Smazat poznámku..." + }, + "ocr": { + "extracted_text": "Extraktovaný text (OCR)", + "extracted_text_title": "Extraktovaný text (OCR)", + "loading_text": "Načítání OCR textu...", + "no_text_available": "Žádný OCR text není k dispozici", + "no_text_explanation": "Tato poznámka nebyla zpracována pro extrakci OCR textu, nebo nebyl nalezen žádný text.", + "failed_to_load": "Nepodařilo se načíst OCR text", + "process_now": "Zpracovat OCR", + "processing": "Zpracovávání...", + "processing_started": "Zpracování OCR bylo zahájeno. Počkejte chvíli a obnovte stránku.", + "processing_failed": "Nepodařilo se zahájit zpracování OCR", + "view_extracted_text": "Zobrazit extraktovaný text (OCR)", + "processing_complete": "Zpracování pomocí OCR bylo dokončeno.", + "text_filtered_low_confidence": "OCR rozpoznal text s jistotou {{confidence}} %, ale výsledek byl vyřazen, protože vaše minimální prahová hodnota je {{threshold}} %.", + "open_media_settings": "Otevřít Nastavení" + }, + "command_palette": { + "tree-action-name": "Strom: {{name}}", + "export_note_title": "Exportovat poznámku", + "export_note_description": "Exportovat aktuální poznámku", + "show_attachments_title": "Zobrazit přílohy", + "show_attachments_description": "Zobrazit přílohy poznámky", + "search_notes_title": "Hledat poznámky", + "search_notes_description": "Otevřít pokročilé hledání", + "search_subtree_title": "Hledat v podstromu", + "search_subtree_description": "Hledat v aktuálním podstromu", + "search_history_title": "Zobrazit historii hledání", + "search_history_description": "Zobrazit předchozí hledání", + "configure_launch_bar_title": "Konfigurovat Launch Bar", + "configure_launch_bar_description": "Otevřít konfiguraci Launch Baru pro přidání nebo odebrání položek." + }, + "content_renderer": { + "open_externally": "Otevřít externě" + }, + "modal": { + "close": "Zavřít", + "help_title": "Zobrazit více informací o této obrazovce" + }, + "call_to_action": { + "next_theme_title": "Vyzkoušejte nové téma Trilium", + "next_theme_message": "Momentálně používáte staré téma, chcete vyzkoušet nové téma?", + "next_theme_button": "Vyzkoušet nové téma", + "background_effects_title": "Efekty pozadí jsou nyní stabilní", + "background_effects_message": "Na zařízeních Windows a macOS jsou efekty pozadí nyní stabilní. Efekty pozadí přidávají uživatelskému rozhraní nádech barvy rozostřením pozadí za ním.", + "background_effects_button": "Povolit efekty pozadí", + "new_layout_title": "Nové rozvržení", + "new_layout_message": "Pro Trilium jsme zavedli modernizované rozvržení. Pás karet byl odstraněn a plynule integrovan do hlavního rozhraní, přičemž nové stavové řádky a rozšiřitelné sekce (jako jsou propagované atributy) převzaly klíčové funkce. \n\nNové rozvržení je padrãoně zapnuté a lze jej dočasně vypnout přes Nastavení → Vzhled.", + "new_layout_button": "Více informací", + "dismiss": "Zavřít" + }, + "settings": { + "related_settings": "Související nastavení" + }, + "settings_appearance": { + "related_code_blocks": "Barevné schéma pro bloky kódu v textových poznámkách", + "related_code_notes": "Barevné schéma pro poznámky kódu", + "ui": "Uživatelské rozhraní", + "ui_old_layout": "Staré rozvržení", + "ui_new_layout": "Nové rozvržení" + }, + "units": { + "percentage": "%" + }, + "pagination": { + "total_notes": "{{count}} poznámek", + "prev_page": "Předchozí stránka", + "next_page": "Další stránka" + }, + "collections": { + "rendering_error": "Obsah nelze zobrazit kvůli chybě." + }, + "note-color": { + "clear-color": "Odstranit barvu poznámky", + "set-color": "Nastavit barvu poznámky", + "set-custom-color": "Nastavit vlastní barvu poznámky" + }, + "popup-editor": { + "maximize": "Přepnout na plný editor" + }, + "server": { + "unknown_http_error_title": "Chyba komunikace se serverem", + "unknown_http_error_content": "Stavový kód: {{statusCode}} \nURL: {{method}} {{url}} \nZpráva: {{message}}", + "traefik_blocks_requests": "Pokud používáte reverzní proxy Traefik, došlo k wprowadzeniu zásadní změny, která ovlivňuje komunikaci se serverem." + }, + "tab_history_navigation_buttons": { + "go-back": "Přejít na předchozí poznámku", + "go-forward": "Přejít na další poznámku" + }, + "breadcrumb": { + "hoisted_badge": "Vyvýšené", + "hoisted_badge_title": "Odstranit z horní části", + "workspace_badge": "Pracovní plocha", + "scroll_to_top_title": "Skočit na začátek poznámky", + "create_new_note": "Vytvořit novou dceřinnou poznámku", + "empty_hide_archived_notes": "Skrýt archivované poznámky" + }, + "breadcrumb_badges": { + "read_only_explicit": "Pouze pro čtení", + "read_only_explicit_description": "Tato poznámka byla ručně nastavena jako pouze pro čtení.\nKliknutím ji můžete dočasně upravit.", + "read_only_auto": "Automatické pouze pro čtení", + "read_only_auto_description": "Tato poznámka byla automaticky nastavena do režimu pouze pro čtení z důvodu výkonu. Toto automatické omezení lze upravit v nastavení.\n\nKliknutím ji můžete dočasně upravit.", + "read_only_temporarily_disabled": "Dočasně upravitelné", + "read_only_temporarily_disabled_description": "Tato poznámka je nyní upravitelná, ale normálně je pouze pro čtení. Jakmile přejdete na jinou poznámku, vrátí se do režimu pouze pro čtení.\n\nKliknutím znovu aktivujete režim pouze pro čtení.", + "shared_publicly": "Veřejně sdílené", + "shared_locally": "Lokálně sdílené", + "shared_copy_to_clipboard": "Kopírovat odkaz do schránky", + "shared_open_in_browser": "Otevřít odkaz v prohlížeči", + "shared_unshare": "Zrušit sdílení", + "clipped_note": "Webový výřez", + "clipped_note_description": "Tato poznámka byla původně převzata z {{url}}.\n\nKliknutím přejdete na zdrojovou webovou stránku.", + "execute_script": "Spustit skript", + "execute_script_description": "Tato poznámka obsahuje skript. Kliknutím jej spustíte.", + "execute_sql": "Spustit SQL", + "execute_sql_description": "Tato poznámka obsahuje SQL dotaz. Kliknutím jej spustíte.", + "save_status_saved": "Uloženo", + "save_status_saving": "Ukládání...", + "save_status_unsaved": "Neuloženo", + "save_status_error": "Uložení selhalo", + "save_status_saving_tooltip": "Změny se ukládají.", + "save_status_unsaved_tooltip": "Neexistují uložené změny. Za chvíli budou uloženy automaticky.", + "save_status_error_tooltip": "Při ukládání poznámky došlo k chybě. Pokud je to možné, zkuste obsah poznámky zkopírovat jinam a aplikaci znovu načíst." + }, + "status_bar": { + "language_title": "Změnit jazyk obsahu", + "note_info_title": "Zobrazit informace o poznámce (např. datum, velikost poznámky)", + "attributes_title": "Vlastní atributy a zděděné atributy", + "note_paths_title": "Cesty poznámky", + "code_note_switcher": "Změnit režim jazyka", + "backlinks_one": "{{count}} zpětný odkaz", + "backlinks_few": "{{count}} zpětné odkazy", + "backlinks_other": "{{count}} zpětných odkazů", + "backlinks_title_one": "Zobrazit zpětný odkaz", + "backlinks_title_few": "Zobrazit zpětné odkazy", + "backlinks_title_other": "Zobrazení zpětných odkazu", + "attachments_one": "{{count}} příloha", + "attachments_few": "{{count}} přílohy", + "attachments_other": "{{count}} příloh", + "attachments_title_one": "Zobrazit přílohu v nové záložce", + "attachments_title_few": "Zobrazit přílohy v nové záložce", + "attachments_title_other": "Zobrazit přílohy v nové záložce", + "attributes_one": "{{count}} atribut", + "attributes_few": "{{count}} atributy", + "attributes_other": "{{count}} atributů", + "note_paths_one": "{{count}} cesta", + "note_paths_few": "{{count}} cesty", + "note_paths_other": "{{count}} cest" + }, + "attributes_panel": { + "title": "Atributy poznámky" + }, + "right_pane": { + "empty_message": "Pro tuto poznámku není nic k zobrazení", + "empty_button": "Skrýt panel", + "toggle": "Přepnout pravý panel", + "custom_widget_go_to_source": "Přejít do zdrojového kódu" + }, + "pdf": { + "pages_alt": "Strana {{pageNumber}}", + "pages_loading": "Načítání...", + "attachments_one": "{{count}} příloha", + "attachments_few": "{{count}} přílohy", + "attachments_other": "{{count}} příloh", + "layers_one": "{{count}} vrstva", + "layers_few": "{{count}} vrstvy", + "layers_other": "{{count}} vrstev", + "pages_one": "{{count}} stránka", + "pages_few": "{{count}} stránky", + "pages_other": "{{count}} stran" + }, + "platform_indicator": { + "available_on": "Dostupné na {{platform}}" + }, + "mobile_tab_switcher": { + "more_options": "Další nastavení", + "title_one": "{{count}} záložka", + "title_few": "{{count}} záložky", + "title_other": "{{count}} záložek" + }, + "bookmark_buttons": { + "bookmarks": "Záložky (oblíbené)" + }, + "active_content_badges": { + "type_icon_pack": "Sada ikon", + "type_backend_script": "Backend skript", + "type_frontend_script": "Frontend skript", + "type_widget": "Widget", + "type_app_css": "Vlastní CSS", + "type_render_note": "Poznámka pro vykreslení", + "type_web_view": "Webové zobrazení", + "type_app_theme": "Vlastní téma", + "toggle_tooltip_enable_tooltip": "Kliknutím tuto {{type}} zapnete.", + "toggle_tooltip_disable_tooltip": "Kliknutím tuto {{type}} vypnete.", + "menu_docs": "Otevřít dokumentaci", + "menu_execute_now": "Spustit skript nyní", + "menu_run": "Spustit automaticky", + "menu_run_disabled": "Ručně", + "menu_run_backend_startup": "Při spuštění backendu", + "menu_run_hourly": "Hodinově", + "menu_run_daily": "Denně", + "menu_run_frontend_startup": "Při spuštění desktop frontend", + "menu_run_mobile_startup": "Při spuštění mobilního rozhraní", + "menu_change_to_widget": "Změnit na widget", + "menu_change_to_frontend_script": "Změnit na frontend skript", + "menu_theme_base": "Základ motivu" + }, + "setup_form": { + "more_info": "Dozvědět se více" + }, + "mermaid": { + "placeholder": "Napište obsah svého Mermaid diagramu nebo použijte jeden z ukázkových diagramů níže.", + "sample_diagrams": "Ukázkové diagramy:", + "sample_flowchart": "Tokový diagram", + "sample_class": "Třída", + "sample_sequence": "Sekvence", + "sample_entity_relationship": "Relace entit", + "sample_state": "Stav", + "sample_mindmap": "Myšlenková mapa", + "sample_architecture": "Architektura", + "sample_block": "Blok", + "sample_c4": "C4", + "sample_gantt": "Gantt", + "sample_git": "Git", + "sample_kanban": "Kanban", + "sample_packet": "Paket", + "sample_pie": "Koláčový graf", + "sample_quadrant": "Čtvrrtinový graf", + "sample_radar": "Radarový graf", + "sample_requirement": "Požadavek", + "sample_sankey": "Sankey", + "sample_timeline": "Osa času", + "sample_treemap": "Stromový graf", + "sample_user_journey": "Cesta uživatele", + "sample_xy": "XY", + "sample_venn": "Vennův diagram", + "sample_ishikawa": "Ishikawa", + "sample_treeview": "Stromové zobrazení", + "sample_wardley": "Wardleyho mapa" + }, + "mind-map": { + "addChild": "Přidat dceřiný", + "addParent": "Přidat rodiče", + "addSibling": "Přidat sourozence", + "removeNode": "Odebrat uzel", + "focus": "Režim soustředění", + "cancelFocus": "Ukončit režim soustředění", + "moveUp": "Posunout nahoru", + "moveDown": "Posunout dolů", + "link": "Odkaz", + "linkBidirectional": "Obousměrný odkaz", + "clickTips": "Klikněte prosím na cílový uzel", + "summary": "Shrnutí" + }, + "llm": { + "settings_title": "AI / LLM", + "settings_description": "Konfigurovat integrace AI a Large Language Model.", + "feature_not_enabled": "Povolte experimentální funkci LLM v Nastavení → Pokročilé → Experimentální funkce pro použití integrací AI.", + "add_provider": "Přidat poskytovatele", + "add_provider_title": "Přidat poskytovatele AI", + "configured_providers": "Konfigurovaní poskytovatelé", + "no_providers_configured": "Ještě nejsou nakonfigurováni žádní poskytovatelé.", + "provider_name": "Název", + "provider_type": "Poskytovatel", + "actions": "Akce", + "delete_provider": "Odstranit", + "delete_provider_confirmation": "Opravdu chcete odstranit poskytovatele \"{{name}}\"?", + "api_key": "API klíč", + "api_key_placeholder": "Zadejte svůj API klíč", + "cancel": "Zrušit", + "mcp_title": "MCP (Model Context Protocol)", + "mcp_enabled": "MCP server", + "mcp_enabled_description": "Zpřístupněte endpoint Model Context Protocol (MCP), aby si AI asistenti pro kódování (např. Claude Code, GitHub Copilot) mohli číst a upravovat vaše poznámky. Endpoint je přístupný pouze z localhost.", + "mcp_endpoint_title": "URL endpointu", + "mcp_endpoint_description": "Přidejte tuto URL adresu do konfigurace MCP svého AI asistenta", + "tools": { + "search_notes": "Hledat poznámky", + "get_note": "Získat poznámku", + "get_note_content": "Získat obsah poznámky", + "update_note_content": "Aktualizovat obsah poznámky", + "append_to_note": "Připojit k poznámce", + "create_note": "Vytvořit poznámku", + "get_attributes": "Získat atributy", + "get_attribute": "Získat atribut", + "set_attribute": "Nastavit atribut", + "delete_attribute": "Odstranit atribut", + "get_child_notes": "Získat dceřiné poznámky", + "get_subtree": "Získat podstrom", + "load_skill": "Načíst dovednost", + "web_search": "Webové hledání", + "note_in_parent": " v ", + "get_attachment": "Získat přílohu", + "get_attachment_content": "Přečíst obsah přílohy" + } } } diff --git a/apps/client/src/translations/de/translation.json b/apps/client/src/translations/de/translation.json index 1275af9825..644b77a63e 100644 --- a/apps/client/src/translations/de/translation.json +++ b/apps/client/src/translations/de/translation.json @@ -88,7 +88,6 @@ "also_delete_note": "Auch die Notiz löschen" }, "delete_notes": { - "delete_notes_preview": "Vorschau der Notizen löschen", "close": "Schließen", "delete_all_clones_description": "auch alle Klone löschen (kann bei letzte Änderungen rückgängig gemacht werden)", "erase_notes_description": "Beim normalen (vorläufigen) Löschen werden die Notizen nur als gelöscht markiert und sie können innerhalb eines bestimmten Zeitraums (im Dialogfeld „Letzte Änderungen“) wiederhergestellt werden. Wenn du diese Option aktivierst, werden die Notizen sofort gelöscht und es ist nicht möglich, die Notizen wiederherzustellen.", @@ -96,9 +95,7 @@ "notes_to_be_deleted": "Folgende Notizen werden gelöscht ({{notesCount}})", "no_note_to_delete": "Es werden keine Notizen gelöscht (nur Klone).", "broken_relations_to_be_deleted": "Folgende Beziehungen werden gelöst und gelöscht ({{ relationCount}})", - "cancel": "Abbrechen", - "ok": "OK", - "deleted_relation_text": "Notiz {{- note}} (soll gelöscht werden) wird von Beziehung {{- relation}} ausgehend von {{- source}} referenziert." + "cancel": "Abbrechen" }, "export": { "export_note_title": "Notiz exportieren", @@ -1386,9 +1383,6 @@ "description": "Diese Optionen gelten nur für Desktop-Builds. Browser verwenden ihre eigene native Rechtschreibprüfung.", "enable": "Aktiviere die Rechtschreibprüfung", "language_code_label": "Sprachcode(s)", - "language_code_placeholder": "zum Beispiel \"en-US\", \"de-AT\"", - "multiple_languages_info": "Mehrere Sprachen können mit einem Komma getrennt werden z.B. \"en-US, de-DE, cs\". ", - "available_language_codes_label": "Verfügbare Sprachcodes:", "restart-required": "Änderungen an den Rechtschreibprüfungsoptionen werden nach dem Neustart der Anwendung wirksam." }, "sync_2": { @@ -1404,8 +1398,7 @@ "test_title": "Synchronisierungstest", "test_description": "Dadurch werden die Verbindung und der Handshake zum Synchronisierungsserver getestet. Wenn der Synchronisierungsserver nicht initialisiert ist, wird er dadurch für die Synchronisierung mit dem lokalen Dokument eingerichtet.", "test_button": "Teste die Synchronisierung", - "handshake_failed": "Handshake des Synchronisierungsservers fehlgeschlagen, Fehler: {{message}}", - "timeout_unit": "Millisekunden" + "handshake_failed": "Handshake des Synchronisierungsservers fehlgeschlagen, Fehler: {{message}}" }, "api_log": { "close": "Schließen" diff --git a/apps/client/src/translations/el/translation.json b/apps/client/src/translations/el/translation.json index 7cb1f9b72d..d502d68fa0 100644 --- a/apps/client/src/translations/el/translation.json +++ b/apps/client/src/translations/el/translation.json @@ -4,7 +4,7 @@ "homepage": "Αρχική Σελίδα:", "app_version": "Έκδοση εφαρμογής:", "db_version": "Έκδοση βάσης δεδομένων:", - "sync_version": "Έκδοση πρωτοκόλου συγχρονισμού:", + "sync_version": "Έκδοση συγχρονισμού:", "build_date": "Ημερομηνία χτισίματος εφαρμογής:", "build_revision": "Αριθμός αναθεώρησης χτισίματος:", "data_directory": "Φάκελος δεδομένων:" diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index 9605212f6e..d5607a95e7 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -88,17 +88,23 @@ "also_delete_note": "Also delete the note" }, "delete_notes": { - "delete_notes_preview": "Delete notes preview", + "title": "Delete notes", "close": "Close", + "clones_label": "Clones", + "delete_clones_description_one": "Also delete {{count}} other clone. Can be undone in recent changes.", + "delete_clones_description_other": "Also delete {{count}} other clones. Can be undone in recent changes.", "delete_all_clones_description": "Delete also all clones (can be undone in recent changes)", - "erase_notes_description": "Normal (soft) deletion only marks the notes as deleted and they can be undeleted (in recent changes dialog) within a period of time. Checking this option will erase the notes immediately and it won't be possible to undelete the notes.", + "erase_notes_label": "Erase permanently", + "erase_notes_description": "Erase notes immediately instead of soft deletion. This cannot be undone and will force application reload.", "erase_notes_warning": "Erase notes permanently (can't be undone), including all clones. This will force application reload.", - "notes_to_be_deleted": "Following notes will be deleted ({{notesCount}})", + "notes_to_be_deleted": "Notes to be deleted ({{notesCount}})", "no_note_to_delete": "No note will be deleted (only clones).", - "broken_relations_to_be_deleted": "Following relations will be broken and deleted ({{ relationCount}})", + "broken_relations_to_be_deleted": "Broken relations ({{relationCount}})", + "table_note_with_relation": "Note with relation", + "table_relation": "Relation", + "table_points_to": "Points to (deleted)", "cancel": "Cancel", - "ok": "OK", - "deleted_relation_text": "Note {{- note}} (to be deleted) is referenced by relation {{- relation}} originating from {{- source}}." + "delete": "Delete" }, "export": { "export_note_title": "Export note", @@ -209,6 +215,7 @@ "box_size_small": "small (~ 10 lines)", "box_size_medium": "medium (~ 30 lines)", "box_size_full": "full (box shows complete text)", + "box_size_expandable": "expandable (collapsed by default)", "button_include": "Include note" }, "info": { @@ -806,7 +813,11 @@ "board": "Board", "presentation": "Presentation", "include_archived_notes": "Show archived notes", - "hide_child_notes": "Hide child notes in tree" + "hide_child_notes": "Hide child notes in tree", + "open_all_in_tabs": "Open all", + "open_all_in_tabs_tooltip": "Open all results in new tabs", + "open_all_confirm": "This will open {{count}} notes in new tabs. Continue?", + "open_all_too_many": "Too many results ({{count}}). Maximum is {{max}}." }, "edited_notes": { "no_edited_notes_found": "No edited notes on this day yet...", @@ -860,7 +871,8 @@ "collapse": "Collapse to normal size", "title": "Note Map", "fix-nodes": "Fix nodes", - "link-distance": "Link distance" + "link-distance": "Link distance", + "too-many-notes": "This subtree contains {{count}} notes, which exceeds the limit of {{max}} that can be displayed in the note map." }, "note_paths": { "title": "Note Paths", @@ -1074,6 +1086,7 @@ "edit_title": "Edit title", "rename_note": "Rename note", "enter_new_title": "Enter new note title:", + "rename_relation": "Rename relation", "remove_relation": "Remove relation", "confirm_remove_relation": "Are you sure you want to remove the relation?", "specify_new_relation_name": "Specify new relation name (allowed characters: alphanumeric, colon and underscore):", @@ -1400,7 +1413,8 @@ "date-and-time": "Date & time", "path": "Path", "database_backed_up_to": "Database has been backed up to {{backupFilePath}}", - "no_backup_yet": "no backup yet" + "no_backup_yet": "no backup yet", + "download": "Download" }, "etapi": { "title": "ETAPI", @@ -1498,18 +1512,21 @@ "spellcheck": { "title": "Spell Check", "description": "These options apply only for desktop builds, browsers will use their own native spell check.", - "enable": "Enable spellcheck", - "language_code_label": "Language code(s)", - "language_code_placeholder": "for example \"en-US\", \"de-AT\"", - "multiple_languages_info": "Multiple languages can be separated by comma, e.g. \"en-US, de-DE, cs\". ", - "available_language_codes_label": "Available language codes:", - "restart-required": "Changes to the spell check options will take effect after application restart." + "enable": "Check spelling", + "language_code_label": "Spell Check Languages", + "restart-required": "Changes to the spell check options will take effect after application restart.", + "custom_dictionary_title": "Custom Dictionary", + "custom_dictionary_description": "Words added to the dictionary are synced across all your devices.", + "custom_dictionary_edit": "Custom words", + "custom_dictionary_edit_description": "Edit the list of words that should not be flagged by the spell checker. Changes will be visible after a restart.", + "custom_dictionary_open": "Edit dictionary", + "related_description": "Configure spell check languages and custom dictionary." }, "sync_2": { "config_title": "Sync Configuration", "server_address": "Server instance address", "timeout": "Sync timeout", - "timeout_unit": "milliseconds", + "timeout_description": "How long to wait before giving up on a slow sync connection. Increase if you have an unstable network.", "proxy_label": "Sync proxy server (optional)", "note": "Note", "note_description": "If you leave the proxy setting blank, the system proxy will be used (applies to desktop/electron build only).", @@ -1660,7 +1677,8 @@ "note_context_enabled": "Click to disable note context: {{title}}", "note_context_disabled": "Click to include current note in context", "no_provider_message": "No AI provider configured. Add one to start chatting.", - "add_provider": "Add AI Provider" + "add_provider": "Add AI Provider", + "stop": "Stop" }, "sidebar_chat": { "title": "AI Chat", @@ -1866,7 +1884,8 @@ "theme_none": "No syntax highlighting", "theme_group_light": "Light themes", "theme_group_dark": "Dark themes", - "copy_title": "Copy to clipboard" + "copy_title": "Copy to clipboard", + "click_to_copy": "Click to copy" }, "classic_editor_toolbar": { "title": "Formatting" @@ -2363,7 +2382,11 @@ "web_search": "Web search", "note_in_parent": " in ", "get_attachment": "Get attachment", - "get_attachment_content": "Read attachment content" + "get_attachment_content": "Read attachment content", + "rename_note": "Rename note", + "delete_note": "Delete note", + "move_note": "Move note", + "clone_note": "Clone note" } } } diff --git a/apps/client/src/translations/es/translation.json b/apps/client/src/translations/es/translation.json index 3756ba8590..c2ea5b0a0c 100644 --- a/apps/client/src/translations/es/translation.json +++ b/apps/client/src/translations/es/translation.json @@ -88,7 +88,6 @@ "also_delete_note": "También eliminar la nota" }, "delete_notes": { - "delete_notes_preview": "Eliminar vista previa de notas", "close": "Cerrar", "delete_all_clones_description": "Eliminar también todos los clones (se puede deshacer en cambios recientes)", "erase_notes_description": "La eliminación normal (suave) solo marca las notas como eliminadas y se pueden recuperar (en el cuadro de diálogo de cambios recientes) dentro de un periodo de tiempo. Al marcar esta opción se borrarán las notas inmediatamente y no será posible recuperarlas.", @@ -96,9 +95,7 @@ "notes_to_be_deleted": "Las siguientes notas serán eliminadas ({{notesCount}})", "no_note_to_delete": "No se eliminará ninguna nota (solo clones).", "broken_relations_to_be_deleted": "Las siguientes relaciones se romperán y serán eliminadas ({{ relationCount}})", - "cancel": "Cancelar", - "ok": "Aceptar", - "deleted_relation_text": "Nota {{- note}} (para ser eliminada) está referenciado por la relación {{- relation}} que se origina en {{- source}}." + "cancel": "Cancelar" }, "export": { "export_note_title": "Exportar nota", @@ -1332,7 +1329,8 @@ "date-and-time": "Fecha y hora", "path": "Ruta", "database_backed_up_to": "Se ha realizado una copia de seguridad de la base de datos en {{backupFilePath}}", - "no_backup_yet": "no hay copia de seguridad todavía" + "no_backup_yet": "no hay copia de seguridad todavía", + "download": "Descargar" }, "etapi": { "title": "ETAPI", @@ -1432,16 +1430,12 @@ "description": "Estas opciones se aplican sólo para compilaciones de escritorio; los navegadores utilizarán su corrector ortográfico nativo.", "enable": "Habilitar corrector ortográfico", "language_code_label": "Código(s) de idioma", - "language_code_placeholder": "por ejemplo \"en-US\", \"de-AT\"", - "multiple_languages_info": "Múltiples idiomas se pueden separar por coma, por ejemplo \"en-US, de-DE, cs\". ", - "available_language_codes_label": "Códigos de idioma disponibles:", "restart-required": "Los cambios en las opciones de corrección ortográfica entrarán en vigor después del reinicio de la aplicación." }, "sync_2": { "config_title": "Configuración de sincronización", "server_address": "Dirección de la instancia del servidor", "timeout": "Tiempo de espera de sincronización (milisegundos)", - "timeout_unit": "milisegundos", "proxy_label": "Sincronizar servidor proxy (opcional)", "note": "Nota", "note_description": "Si deja la configuración del proxy en blanco, se utilizará el proxy del sistema (se aplica únicamente a la compilación de escritorio/electron).", diff --git a/apps/client/src/translations/fi/translation.json b/apps/client/src/translations/fi/translation.json index fe6d636f6e..6791899ea4 100644 --- a/apps/client/src/translations/fi/translation.json +++ b/apps/client/src/translations/fi/translation.json @@ -62,12 +62,10 @@ "also_delete_note": "Poista myös muistio" }, "delete_notes": { - "delete_notes_preview": "Poista muistion esikatselu", "close": "Sulje", "notes_to_be_deleted": "Seuraavat muistiot tullaan poistamaan ({{notesCount}})", "no_note_to_delete": "Muistioita ei poisteta (vain kopiot).", - "cancel": "Peruuta", - "ok": "OK" + "cancel": "Peruuta" }, "export": { "export_note_title": "Vie muistio", diff --git a/apps/client/src/translations/fr/translation.json b/apps/client/src/translations/fr/translation.json index 6cba618672..082f172a47 100644 --- a/apps/client/src/translations/fr/translation.json +++ b/apps/client/src/translations/fr/translation.json @@ -88,7 +88,6 @@ "also_delete_note": "Supprimer également la note" }, "delete_notes": { - "delete_notes_preview": "Supprimer la note", "close": "Fermer", "delete_all_clones_description": "Supprimer aussi les clones (peut être annulé dans des modifications récentes)", "erase_notes_description": "La suppression normale (douce) marque uniquement les notes comme supprimées et elles peuvent être restaurées (dans la boîte de dialogue des Modifications récentes) dans un délai donné. Cocher cette option effacera les notes immédiatement et il ne sera pas possible de les restaurer.", @@ -96,9 +95,7 @@ "notes_to_be_deleted": "Les notes suivantes seront supprimées ({{notesCount}})", "no_note_to_delete": "Aucune note ne sera supprimée (uniquement les clones).", "broken_relations_to_be_deleted": "Les relations suivantes seront rompues et supprimées ({{ relationCount}})", - "cancel": "Annuler", - "ok": "OK", - "deleted_relation_text": "Note {{- note}} (à supprimer) est référencée dans la relation {{- relation}} provenant de {{- source}}." + "cancel": "Annuler" }, "export": { "export_note_title": "Exporter la note", @@ -1391,9 +1388,6 @@ "description": "Ces options s'appliquent uniquement aux versions de bureau, les navigateurs utiliseront leur propre vérification orthographique native.", "enable": "Activer la vérification orthographique", "language_code_label": "Code(s) de langue", - "language_code_placeholder": "par exemple \"fr-FR\", \"en-US\", \"de-AT\"", - "multiple_languages_info": "Plusieurs langues peuvent être séparées par une virgule, par ex. \"fr-FR, en-US, de-DE, cs\". ", - "available_language_codes_label": "Codes de langue disponibles :", "restart-required": "Les modifications apportées aux options de vérification orthographique prendront effet après le redémarrage de l'application." }, "sync_2": { @@ -1409,8 +1403,7 @@ "test_title": "Test de synchronisation", "test_description": "Testera la connexion et la prise de contact avec le serveur de synchronisation. Si le serveur de synchronisation n'est pas initialisé, cela le configurera pour qu'il se synchronise avec le document local.", "test_button": "Tester la synchronisation", - "handshake_failed": "Échec de la négociation avec le serveur de synchronisation, erreur : {{message}}", - "timeout_unit": "millisecondes" + "handshake_failed": "Échec de la négociation avec le serveur de synchronisation, erreur : {{message}}" }, "api_log": { "close": "Fermer" diff --git a/apps/client/src/translations/ga/translation.json b/apps/client/src/translations/ga/translation.json index f6b858de3f..6854c3ff77 100644 --- a/apps/client/src/translations/ga/translation.json +++ b/apps/client/src/translations/ga/translation.json @@ -119,7 +119,6 @@ "also_delete_note": "Scrios an nóta freisin" }, "delete_notes": { - "delete_notes_preview": "Réamhamharc ar scriosadh nótaí", "close": "Dún", "delete_all_clones_description": "Scrios gach clón freisin (is féidir é seo a chealú in athruithe le déanaí)", "erase_notes_description": "Ní mharcálann scriosadh gnáth (bog) ach na nótaí mar scriosta agus is féidir iad a dhíscriosadh (sa dialóg athruithe le déanaí) laistigh de thréimhse ama. Scriosfar na nótaí láithreach má sheiceálann tú an rogha seo agus ní bheidh sé indéanta na nótaí a dhíscriosadh.", @@ -127,9 +126,7 @@ "notes_to_be_deleted": "Scriosfar na nótaí seo a leanas ({{notesCount}})", "no_note_to_delete": "Ní scriosfar aon nóta (clóin amháin).", "broken_relations_to_be_deleted": "Brisfear agus scriosfar na caidrimh seo a leanas ({{ relationCount}})", - "cancel": "Cealaigh", - "ok": "Ceart go leor", - "deleted_relation_text": "Tá tagairt don nóta {{- note}} (le scriosadh) le gaol {{- relation}} a thagann ó {{- source}}." + "cancel": "Cealaigh" }, "export": { "export_note_title": "Nóta easpórtála", @@ -1071,7 +1068,8 @@ "note_already_in_diagram": "Tabhair faoi deara go bhfuil \"{{title}}\" sa léaráid cheana féin.", "enter_title_of_new_note": "Cuir isteach teideal an nóta nua", "default_new_note_title": "nóta nua", - "click_on_canvas_to_place_new_note": "Cliceáil ar chanbhás chun nóta nua a chur" + "click_on_canvas_to_place_new_note": "Cliceáil ar chanbhás chun nóta nua a chur", + "rename_relation": "Athainmnigh an gaol" }, "backend_log": { "refresh": "Athnuachan" @@ -1468,18 +1466,20 @@ "spellcheck": { "title": "Seiceáil Litrithe", "description": "Ní bhaineann na roghanna seo ach le leaganacha deisce, úsáidfidh brabhsálaithe a seiceáil litrithe dúchasach féin.", - "enable": "Cumasaigh seiceáil litrithe", - "language_code_label": "Cód(anna) teanga", - "language_code_placeholder": "mar shampla \"en-US\", \"de-AT\"", - "multiple_languages_info": "Is féidir camóg a úsáid chun teangacha iolracha a dheighilt óna chéile, m.sh. \"en-US, de-DE, cs\". ", - "available_language_codes_label": "Cóid teanga atá ar fáil:", - "restart-required": "Tiocfaidh athruithe ar na roghanna seiceála litrithe i bhfeidhm tar éis atosú an fheidhmchláir." + "enable": "Seiceáil litriú", + "language_code_label": "Seiceáil Litrithe Teangacha", + "restart-required": "Tiocfaidh athruithe ar na roghanna seiceála litrithe i bhfeidhm tar éis atosú an fheidhmchláir.", + "custom_dictionary_title": "Foclóir Saincheaptha", + "custom_dictionary_description": "Déantar focail a chuirtear leis an bhfoclóir a sioncrónú ar fud do ghléasanna go léir.", + "custom_dictionary_edit": "Focail saincheaptha", + "custom_dictionary_edit_description": "Cuir an liosta focal in eagar nach ceart don seiceálaí litrithe a mharcáil. Beidh athruithe le feiceáil tar éis atosaithe.", + "custom_dictionary_open": "Cuir an foclóir in eagar", + "related_description": "Cumraigh teangacha seiceála litrithe agus foclóir saincheaptha." }, "sync_2": { "config_title": "Cumraíocht Sioncrónaithe", "server_address": "Seoladh sampla an fhreastalaí", "timeout": "Am scoir sioncrónaithe", - "timeout_unit": "milleasoicindí", "proxy_label": "Sioncrónaigh freastalaí seachfhreastalaí (roghnach)", "note": "Nóta", "note_description": "Má fhágann tú an socrú seachfhreastalaí bán, úsáidfear seachfhreastalaí an chórais (baineann sé le tógáil deisce/leictreon amháin).", @@ -2294,7 +2294,9 @@ "sample_user_journey": "Turas Úsáideora", "sample_xy": "XY", "sample_venn": "Venn", - "sample_ishikawa": "Ishikawa" + "sample_ishikawa": "Ishikawa", + "sample_treeview": "Radharc Crann", + "sample_wardley": "Léarscáil Wardley" }, "llm_chat": { "placeholder": "Clóscríobh teachtaireacht...", @@ -2404,6 +2406,9 @@ "processing": "Ag próiseáil...", "processing_started": "Tá próiseáil OCR tosaithe. Fan nóiméad agus athnuachan le do thoil.", "processing_failed": "Theip ar phróiseáil OCR a thosú", - "view_extracted_text": "Féach ar théacs eastósctha (OCR)" + "view_extracted_text": "Féach ar théacs eastósctha (OCR)", + "processing_complete": "Próiseáil OCR críochnaithe.", + "text_filtered_low_confidence": "Bhraith OCR téacs le muinín {{confidence}}%, ach caitheadh leis é mar is é {{threshold}}% an tairseach íosta atá agat.", + "open_media_settings": "Oscail Socruithe" } } diff --git a/apps/client/src/translations/hi/translation.json b/apps/client/src/translations/hi/translation.json index b11e731125..a233ce587f 100644 --- a/apps/client/src/translations/hi/translation.json +++ b/apps/client/src/translations/hi/translation.json @@ -94,7 +94,6 @@ "if_you_dont_check": "अगर आप इसे चेक नहीं करते हैं, तो नोट केवल रिलेशन मैप से हटाया जाएगा।" }, "delete_notes": { - "delete_notes_preview": "नोट्स प्रिव्यू डिलीट करें", "close": "बंद करें", "delete_all_clones_description": "सभी क्लोन भी डिलीट करें (हाल के बदलावों में वापस ला सकते हैं)", "erase_notes_description": "सामान्य (सॉफ्ट) डिलीट करने पर नोट केवल 'डिलीटेड' मार्क होते हैं और उन्हें एक निश्चित समय के भीतर (हाल के बदलावों वाले डायलॉग में) वापस लाया जा सकता है। इस विकल्प को चुनने पर नोट तुरंत पूरी तरह मिटा दिए जाएंगे और उन्हें वापस लाना संभव नहीं होगा।", @@ -102,9 +101,7 @@ "notes_to_be_deleted": "निम्नलिखित नोट डिलीट कर दिए जाएंगे ({{notesCount}})", "no_note_to_delete": "कोई भी नोट डिलीट नहीं होगा (केवल क्लोन हटाए जाएंगे)।", "broken_relations_to_be_deleted": "निम्नलिखित रिलेशन टूट जाएंगे और डिलीट हो जाएंगे ({{relationCount}})", - "cancel": "रद्द करें", - "ok": "ठीक है", - "deleted_relation_text": "नोट {{- note}} (जिसे डिलीट किया जाना है) का संदर्भ {{- source}} से शुरू होने वाले रिलेशन {{- relation}} में दिया गया है।" + "cancel": "रद्द करें" }, "branch_prefix": { "edit_branch_prefix": "ब्रांच प्रीफ़िक्स एडिट करें", @@ -1461,16 +1458,12 @@ "description": "ये विकल्प सिर्फ़ डेस्कटॉप वर्जन के लिए हैं, ब्राउज़र अपना स्पेल चेक इस्तेमाल करेंगे।", "enable": "स्पेल चेक चालू करें", "language_code_label": "भाषा कोड (Language code)", - "language_code_placeholder": "जैसे \"en-US\", \"hi-IN\"", - "multiple_languages_info": "कई भाषाओं को कॉमा से अलग किया जा सकता है, जैसे \"en-US, hi-IN\"। ", - "available_language_codes_label": "उपलब्ध भाषा कोड:", "restart-required": "स्पेल चेक में बदलाव ऐप रीस्टार्ट करने के बाद ही दिखेंगे।" }, "sync_2": { "config_title": "सिंक कॉन्फ़िगरेशन", "server_address": "सर्वर एड्रेस (Address)", "timeout": "सिंक समय-सीमा (Timeout)", - "timeout_unit": "मिलीसेकंड (milliseconds)", "proxy_label": "सिंक प्रॉक्सी सर्वर (वैकल्पिक)", "note": "नोट", "note_description": "अगर आप प्रॉक्सी खाली छोड़ते हैं, तो सिस्टम प्रॉक्सी का इस्तेमाल होगा।", diff --git a/apps/client/src/translations/id/translation.json b/apps/client/src/translations/id/translation.json index 68c60e7259..ad5cf53609 100644 --- a/apps/client/src/translations/id/translation.json +++ b/apps/client/src/translations/id/translation.json @@ -76,7 +76,6 @@ "confirmation": "Konfirmasi" }, "delete_notes": { - "delete_notes_preview": "Hapus pratinjau catatan", "close": "Tutup", "delete_all_clones_description": "Hapus seluruh duplikat (bisa dikembalikan di menu revisi)", "erase_notes_description": "Penghapusan normal hanya menandai catatan sebagai dihapus dan dapat dipulihkan (melalui dialog versi revisi) dalam jangka waktu tertentu. Mencentang opsi ini akan menghapus catatan secara permanen seketika dan catatan tidak akan bisa dipulihkan kembali.", @@ -84,9 +83,7 @@ "notes_to_be_deleted": "Catatan-catatan berikut akan dihapuskan ({{notesCount}})", "no_note_to_delete": "Tidak ada Catatan yang akan dihapus (hanya duplikat).", "broken_relations_to_be_deleted": "Hubungan berikut akan diputus dan dihapus ({{ relationCount}})", - "cancel": "Batalkan", - "ok": "Setuju", - "deleted_relation_text": "Catatan {{- note}} (yang akan dihapus) dirujuk oleh relasi {{- relation}} yang berasal dari {{- source}}." + "cancel": "Batalkan" }, "clone_to": { "clone_notes_to": "Duplikat catatan ke…", diff --git a/apps/client/src/translations/it/translation.json b/apps/client/src/translations/it/translation.json index 8776e64edd..10a73ac589 100644 --- a/apps/client/src/translations/it/translation.json +++ b/apps/client/src/translations/it/translation.json @@ -88,17 +88,14 @@ "also_delete_note": "Rimuove anche la nota" }, "delete_notes": { - "ok": "OK", "close": "Chiudi", - "delete_notes_preview": "Anteprima di eliminazione delle note", "delete_all_clones_description": "Elimina anche tutti i cloni (può essere ripristinato nella sezione cambiamenti recenti)", "erase_notes_description": "L'eliminazione normale (soft) marca le note come eliminate e potranno essere recuperate entro un certo lasso di tempo (dalla finestra dei cambiamenti recenti). Selezionando questa opzione le note si elimineranno immediatamente e non sarà possibile recuperarle.", "erase_notes_warning": "Elimina le note in modo permanente (non potrà essere disfatto), compresi tutti i cloni. Ciò forzerà un nuovo caricamento dell'applicazione.", "cancel": "Annulla", "notes_to_be_deleted": "Le seguenti note saranno eliminate ({{notesCount}})", "no_note_to_delete": "Nessuna nota sarà eliminata (solo i cloni).", - "broken_relations_to_be_deleted": "Le seguenti relazioni saranno interrotte ed eliminate ({{relationCount}})", - "deleted_relation_text": "La nota {{- note}} (da eliminare) è referenziata dalla relazione {{- relation}} originata da {{- source}}." + "broken_relations_to_be_deleted": "Le seguenti relazioni saranno interrotte ed eliminate ({{relationCount}})" }, "info": { "okButton": "OK", @@ -497,7 +494,6 @@ "proxy_label": "Server Proxy per la sincronizzazione (opzionale)", "test_title": "Test di sincronizzazione", "timeout": "Timeout per la sincronizzazione", - "timeout_unit": "millisecondi", "save": "Salva", "help": "Aiuto", "server_address": "Indirizzo dell'istanza del server", @@ -538,12 +534,12 @@ "new_tab": "Nuova scheda" }, "toc": { - "table_of_contents": "Sommario", + "table_of_contents": "Tabella dei Contenuti", "options": "Opzioni", "no_headings": "Nessun titolo." }, "table_of_contents": { - "title": "Sommario", + "title": "Tabella dei Contenuti", "description": "L'indice apparirà nelle note di testo quando la nota contiene più di un numero definito di titoli. È possibile personalizzare questo numero:", "unit": "titoli", "disable_info": "È anche possibile utilizzare questa opzione per disattivare efficacemente l'indice impostando un numero molto alto.", @@ -593,7 +589,7 @@ "collapseExpand": "collassa/espande il nodo", "notSet": "non impostato", "goBackForwards": "indietro/avanti nella cronologia", - "showJumpToNoteDialog": "mostra finestra \"Vai a\"", + "showJumpToNoteDialog": "mostra \"Vai a\"", "title": "Scheda riassuntiva", "noteNavigation": "Nota navigazione", "scrollToActiveNote": "scorri fino alla nota attiva", @@ -853,7 +849,7 @@ "archived": "Le note con questa etichetta non saranno visibili per impostazione predefinita nei risultati di ricerca (anche nelle finestre di dialogo Vai a, Aggiungi collegamento ecc.).", "run_on_instance": "Definire su quale istanza di Trilium eseguire questa operazione. L'impostazione predefinita è tutte le istanze.", "exclude_from_export": "le note (con la loro sottostruttura) non saranno incluse in nessuna esportazione di note", - "run": "definisce su quali eventi deve essere eseguito lo script. I valori possibili sono:\n
    \n
  • frontendStartup - quando il frontend Trilium viene avviato (o aggiornato), ma non su dispositivi mobili.
  • \n
  • mobileStartup - quando il frontend Trilium viene avviato (o aggiornato) su dispositivi mobili.
  • \n
  • backendStartup - quando viene avviato il backend Trilium
  • \n
  • hourly - eseguire una volta all'ora. È possibile utilizzare l'etichetta aggiuntiva runAtHour per specificare a che ora.
  • \n
  • daily - eseguire una volta al giorno
  • \n
", + "run": "definisce su quali eventi deve essere eseguito lo script. I valori possibili sono:\n
    \n
  • frontendStartup - quando il frontend Trilium viene avviato (o aggiornato), ma non su dispositivi mobili.
  • \n
  • mobileStartup - quando il frontend Trilium viene avviato (o aggiornato) su dispositivi mobili.
  • \n
  • backendStartup - quando viene avviato il backend Trilium.
  • \n
  • hourly - eseguire una volta all'ora. È possibile utilizzare l'etichetta aggiuntiva runAtHour per specificare a che ora.
  • \n
  • daily - eseguire una volta al giorno.
  • \n
", "run_at_hour": "A che ora deve essere eseguito. Deve essere utilizzato insieme a #run=hourly. Può essere definito più volte per più esecuzioni durante il giorno.", "disable_inclusion": "gli script con questa etichetta non saranno inclusi nell'esecuzione dello script principale.", "sorted": "mantiene le note figlie ordinate alfabeticamente per titolo", @@ -1100,7 +1096,7 @@ "show_help": "Mostra aiuto", "about": "Informazioni su Trilium Notes", "logout": "Esci", - "show-cheatsheet": "Mostra il foglietto illustrativo", + "show-cheatsheet": "Mostra la scheda riassuntiva", "toggle-zen-mode": "Modalità Zen", "new-version-available": "Nuovo aggiornamento disponibile", "download-update": "Ottieni la versione {{latestVersion}}", @@ -1149,7 +1145,8 @@ "export_as_image": "Esporta come immagine", "export_as_image_png": "PNG (raster)", "export_as_image_svg": "SVG (vector)", - "note_map": "Mappa" + "note_map": "Mappa", + "view_ocr_text": "Visualizza il testo OCR" }, "onclick_button": { "no_click_handler": "Il widget pulsante '{{componentId}}' non ha un gestore di clic definito" @@ -1439,7 +1436,8 @@ "note_already_in_diagram": "Nota che \"{{title}}\" è già presente nel diagramma.", "enter_title_of_new_note": "Inserisci il titolo della nuova nota", "default_new_note_title": "nuova nota", - "click_on_canvas_to_place_new_note": "Clicca sulla tela per inserire una nuova nota" + "click_on_canvas_to_place_new_note": "Clicca sulla tela per inserire una nuova nota", + "rename_relation": "Rinomina relazione" }, "vacuum_database": { "title": "Pulizia del database", @@ -1541,12 +1539,28 @@ }, "images": { "images_section_title": "Immagini", - "download_images_automatically": "Scarica automaticamente le immagini per l'utilizzo offline.", - "download_images_description": "L'HTML incollato può contenere riferimenti a immagini online; Trilium troverà tali riferimenti e scaricherà le immagini in modo che siano disponibili offline.", - "enable_image_compression": "Abilita la compressione delle immagini", - "max_image_dimensions": "Larghezza/altezza massima di un'immagine (l'immagine verrà ridimensionata se supera questa impostazione).", + "download_images_automatically": "Scarica automaticamente le immagini", + "download_images_description": "Scarica le immagini online a cui si fa riferimento nel codice HTML incollato, in modo che siano disponibili offline.", + "enable_image_compression": "Compressione delle immagini", + "max_image_dimensions": "Dimensioni massime dell'immagine", "max_image_dimensions_unit": "pixel", - "jpeg_quality_description": "Qualità JPEG (10 - qualità peggiore, 100 - qualità migliore, 50 - 85 è consigliato)" + "jpeg_quality_description": "Il range consigliato è compreso tra 50 e 85. Valori più bassi riducono le dimensioni del file, mentre valori più alti preservano i dettagli.", + "enable_image_compression_description": "Comprimi e ridimensiona le immagini al momento del caricamento o dell'inserimento.", + "max_image_dimensions_description": "Le immagini che superano queste dimensioni verranno ridimensionate automaticamente.", + "jpeg_quality": "Qualità JPEG", + "ocr_section_title": "Estrazione di testo (OCR)", + "ocr_related_content_languages": "Lingue dei contenuti (utilizzate per l'estrazione del testo)", + "ocr_auto_process": "Elaborazione automatica dei nuovi file", + "ocr_auto_process_description": "Estrai automaticamente il testo dai file appena caricati o incollati.", + "ocr_min_confidence": "Livello minimo di confidenza", + "ocr_confidence_description": "Estrai solo il testo che supera questa soglia di affidabilità. Valori inferiori includono più testo, ma potrebbero risultare meno accurati.", + "batch_ocr_title": "Elabora i file esistenti", + "batch_ocr_description": "Estrai il testo da tutte le immagini, i PDF e i documenti Office presenti nei tuoi appunti. L'operazione potrebbe richiedere un po' di tempo a seconda del numero di file.", + "batch_ocr_start": "Avvia l'elaborazione in batch", + "batch_ocr_starting": "Avvio dell'elaborazione in batch...", + "batch_ocr_progress": "Elaborazione di {{processed}} su {{total}} file...", + "batch_ocr_completed": "Elaborazione in batch completata! Sono stati elaborati {{processed}} file.", + "batch_ocr_error": "Errore durante l'elaborazione in batch: {{error}}" }, "attachment_erasure_timeout": { "attachment_erasure_timeout": "Timeout cancellazione allegato", @@ -1654,12 +1668,15 @@ "spellcheck": { "title": "Controllo ortografico", "description": "Queste opzioni sono valide solo per le versioni desktop; i browser utilizzeranno il proprio controllo ortografico nativo.", - "enable": "Abilita il controllo ortografico", - "language_code_label": "Codice/i della lingua", - "language_code_placeholder": "ad esempio \"en-US\", \"de-AT\"", - "multiple_languages_info": "È possibile separare più lingue con una virgola, ad esempio \"en-US, de-DE, cs\". ", - "available_language_codes_label": "Codici lingua disponibili:", - "restart-required": "Le modifiche alle opzioni di controllo ortografico avranno effetto dopo il riavvio dell'applicazione." + "enable": "Controlla l'ortografia", + "language_code_label": "Lingue del controllo ortografico", + "restart-required": "Le modifiche alle opzioni di controllo ortografico avranno effetto dopo il riavvio dell'applicazione.", + "custom_dictionary_title": "Dizionario personalizzato", + "custom_dictionary_description": "Le parole aggiunte al dizionario vengono sincronizzate su tutti i tuoi dispositivi.", + "custom_dictionary_edit": "Parole personalizzate", + "custom_dictionary_edit_description": "Modifica l'elenco delle parole che non devono essere segnalate dal correttore ortografico. Le modifiche saranno visibili dopo il riavvio.", + "custom_dictionary_open": "Modifica il dizionario", + "related_description": "Configura le lingue del controllo ortografico e il dizionario personalizzato." }, "api_log": { "close": "Vicino" @@ -1940,7 +1957,7 @@ }, "content_language": { "title": "Lingue dei contenuti", - "description": "Seleziona una o più lingue che desideri visualizzare nella sezione \"Proprietà di base\" di una nota di testo di sola lettura o modificabile. Ciò consentirà funzionalità come il controllo ortografico o il supporto per la scrittura da destra a sinistra." + "description": "Seleziona una o più lingue che devono comparire nell'elenco di selezione delle lingue nella sezione \"Proprietà di base\" di una nota di testo in sola lettura o modificabile. Ciò consentirà di utilizzare funzioni quali il controllo ortografico, il supporto per la scrittura da destra a sinistra e l'estrazione del testo (OCR)." }, "switch_layout_button": { "title_vertical": "Sposta il riquadro di modifica in basso", @@ -2247,7 +2264,9 @@ "sample_user_journey": "Percorso dell'utente", "sample_xy": "XY", "sample_venn": "Venn", - "sample_ishikawa": "Ishikawa" + "sample_ishikawa": "Ishikawa", + "sample_treeview": "TreeView", + "sample_wardley": "Mappa di Wardley" }, "llm_chat": { "placeholder": "Scrivi un messaggio...", @@ -2278,7 +2297,8 @@ "note_context_enabled": "Clicca qui per disattivare il contesto della nota: {{title}}", "note_context_disabled": "Clicca per includere la nota corrente nel contesto", "no_provider_message": "Non è stato configurato alcun fornitore di IA. Aggiungine uno per iniziare a chattare.", - "add_provider": "Aggiungi un fornitore di IA" + "add_provider": "Aggiungi un fornitore di IA", + "sources_summary": "{{count}} fonti provenienti da {{sites}} siti" }, "sidebar_chat": { "title": "Chat AI", @@ -2304,6 +2324,61 @@ "delete_provider_confirmation": "Sei sicuro di voler eliminare il provider \"{{name}}\"?", "api_key": "Chiave API", "api_key_placeholder": "Inserisci la tua chiave API", - "cancel": "Annulla" + "cancel": "Annulla", + "feature_not_enabled": "Abilita la funzione sperimentale LLM in Impostazioni → Avanzate → Funzioni sperimentali per utilizzare le integrazioni basate sull'intelligenza artificiale.", + "mcp_title": "MCP (Model Context Protocol)", + "mcp_enabled": "Server MCP", + "mcp_enabled_description": "Rendi pubblico un endpoint MCP (Model Context Protocol) in modo che gli assistenti di programmazione basati sull'intelligenza artificiale (ad esempio Claude Code, GitHub Copilot) possano leggere e modificare le tue note. L'endpoint è accessibile solo da localhost.", + "mcp_endpoint_title": "URL dell'endpoint", + "mcp_endpoint_description": "Aggiungi questo URL alla configurazione MCP del tuo assistente AI", + "tools": { + "search_notes": "Cerca nelle note", + "get_note": "Prendi nota", + "get_note_content": "Visualizza il contenuto della nota", + "update_note_content": "Aggiorna il contenuto della nota", + "append_to_note": "Aggiungi alla nota", + "create_note": "Crea nota", + "get_attributes": "Recupera gli attributi", + "get_attribute": "Ottieni attributo", + "set_attribute": "Imposta attributo", + "delete_attribute": "Elimina attributo", + "get_child_notes": "Recupera le note relative ai figli", + "get_subtree": "Ottieni sottostruttura", + "load_skill": "Carica skill", + "web_search": "Ricerca sul web", + "note_in_parent": " in ", + "get_attachment": "Scarica l'allegato", + "get_attachment_content": "Leggi il contenuto dell'allegato" + } + }, + "ocr": { + "extracted_text": "Testo estratto (OCR)", + "extracted_text_title": "Testo estratto (OCR)", + "loading_text": "Caricamento del testo OCR in corso...", + "no_text_available": "Non è disponibile alcun testo OCR", + "no_text_explanation": "Questo documento non è stato sottoposto a elaborazione OCR per l'estrazione del testo oppure non è stato trovato alcun testo.", + "failed_to_load": "Impossibile caricare il testo OCR", + "process_now": "Elaborazione OCR", + "processing": "Elaborazione in corso...", + "processing_started": "L'elaborazione OCR è stata avviata. Attendere qualche istante e aggiorna.", + "processing_complete": "Elaborazione OCR completata.", + "processing_failed": "Impossibile avviare l'elaborazione OCR", + "text_filtered_low_confidence": "L'OCR ha rilevato il testo con un livello di affidabilità del {{confidence}}%, ma è stato scartato perché la soglia minima impostata è del {{threshold}}%.", + "open_media_settings": "Apri Impostazioni", + "view_extracted_text": "Visualizza il testo estratto (OCR)" + }, + "mind-map": { + "addChild": "Aggiungi figlio", + "addParent": "Aggiungi genitore", + "addSibling": "Aggiungi un fratello o una sorella", + "removeNode": "Rimuovi nodo", + "focus": "Modalità Focus", + "cancelFocus": "Annulla modalità Focus", + "moveUp": "Sposta su", + "moveDown": "Sposta giù", + "link": "Collegamento", + "linkBidirectional": "Collegamento bidirezionale", + "clickTips": "Clicca sul nodo di destinazione", + "summary": "Sommario" } } diff --git a/apps/client/src/translations/ja/translation.json b/apps/client/src/translations/ja/translation.json index 5564080be4..e808ec0118 100644 --- a/apps/client/src/translations/ja/translation.json +++ b/apps/client/src/translations/ja/translation.json @@ -111,11 +111,8 @@ "notes_to_be_deleted": "以下のノートが削除されます ({{notesCount}})", "no_note_to_delete": "ノートは削除されません(クローンのみ)。", "cancel": "キャンセル", - "ok": "OK", "close": "閉じる", - "delete_notes_preview": "ノートのプレビューを削除", - "broken_relations_to_be_deleted": "次のリレーション ({{relationCount}})は壊れているので消去されます", - "deleted_relation_text": "削除予定のノート{{- note}}は{{- source}}からリレーション{{- relation}}によって参照されています." + "broken_relations_to_be_deleted": "次のリレーション ({{relationCount}})は壊れているので消去されます" }, "calendar": { "mon": "月", @@ -576,7 +573,10 @@ "expand_first_level": "直下の子を展開", "expand_nth_level": "{{depth}} 階層下まで展開", "expand_all_levels": "すべての階層を展開", - "hide_child_notes": "ツリー内の子ノートを非表示" + "hide_child_notes": "ツリー内の子ノートを非表示", + "open_all_in_tabs": "すべて開く", + "open_all_in_tabs_tooltip": "すべての結果を新しいタブで開く", + "open_all_confirm": "{{count}} 件のノートが新しいタブで開かれます。続行しますか?" }, "note_types": { "geo-map": "ジオマップ", @@ -1001,7 +1001,8 @@ "date-and-time": "日時", "path": "パス", "database_backed_up_to": "データベースは{{backupFilePath}}にバックアップされました", - "no_backup_yet": "バックアップがありません" + "no_backup_yet": "バックアップがありません", + "download": "ダウンロード" }, "password": { "wiki": "wiki", @@ -1027,18 +1028,20 @@ "spellcheck": { "title": "スペルチェック", "description": "これらのオプションはデスクトップビルドにのみ適用され、ブラウザはそれぞれのネイティブスペルチェックを使用します。", - "enable": "スペルチェックを有効", - "language_code_label": "言語コード", - "language_code_placeholder": "例えば \"en-US\", \"de-AT\"", - "multiple_languages_info": "複数の言語はカンマで区切ることができます。例: \"en-US, de-DE, cs\"。 ", - "available_language_codes_label": "使用可能な言語コード:", - "restart-required": "スペルチェックオプションの変更は、アプリケーションの再起動後に有効になります。" + "enable": "スペルチェック", + "language_code_label": "スペルチェック対応言語", + "restart-required": "スペルチェックオプションの変更は、アプリケーションの再起動後に有効になります。", + "custom_dictionary_title": "カスタム辞書", + "custom_dictionary_description": "辞書に追加した単語は、すべてのデバイス間で同期されます。", + "custom_dictionary_edit": "カスタム単語", + "custom_dictionary_edit_description": "スペルチェッカーでエラーとして検出されないようにする単語リストを編集します。変更は再起動後に反映されます。", + "custom_dictionary_open": "辞書の編集", + "related_description": "スペルチェック対応言語とカスタム辞書を設定します。" }, "sync_2": { "config_title": "同期設定", "server_address": "サーバーインスタンスのアドレス", "timeout": "同期タイムアウト", - "timeout_unit": "ミリ秒", "proxy_label": "同期プロキシサーバー(任意)", "note": "注", "note_description": "プロキシ設定を空白のままにすると、システムプロキシが使用されます(デスクトップ/electronビルドにのみ適用されます)。", @@ -1048,7 +1051,8 @@ "test_title": "同期のテスト", "test_description": "これは同期サーバとの接続とハンドシェイクをテストします。同期サーバーが初期化されていない場合、ローカルドキュメントと同期するように設定します。", "test_button": "同期試行", - "handshake_failed": "同期サーバーのハンドシェイクに失敗しました。エラー: {{message}}" + "handshake_failed": "同期サーバーのハンドシェイクに失敗しました。エラー: {{message}}", + "timeout_description": "同期接続が遅い場合に、接続を諦めるまでの待機時間。ネットワークが不安定な場合は、この時間を長く設定してください。" }, "api_log": { "close": "閉じる" @@ -1539,7 +1543,8 @@ "collapse": "通常サイズに折りたたむ", "title": "ノートマップ", "link-distance": "リンク距離", - "fix-nodes": "ノードを修正" + "fix-nodes": "ノードを修正", + "too-many-notes": "このサブツリーには {{count}} 件のノートが含まれており、ノートマップに表示できる {{max}} の上限を超えています。" }, "owned_attribute_list": { "owned_attributes": "所有属性" @@ -1570,7 +1575,8 @@ "click_on_canvas_to_place_new_note": "キャンバスをクリックして新しいノートを配置", "connection_exists": "これらのノート間の接続 '{{name}}' は既に存在します。", "start_dragging_relations": "ここからリレーションをドラッグして、別のノートにドロップします。", - "note_already_in_diagram": "ノート「{{title}}」はすでに図に含まれています。" + "note_already_in_diagram": "ノート「{{title}}」はすでに図に含まれています。", + "rename_relation": "リレーション名の変更" }, "database_anonymization": { "title": "データベースの匿名化", @@ -2234,7 +2240,9 @@ "sample_user_journey": "ユーザージャーニー図", "sample_xy": "XY チャート", "sample_venn": "ベン図", - "sample_ishikawa": "石川図" + "sample_ishikawa": "石川図", + "sample_treeview": "ツリービュー", + "sample_wardley": "ウォードリーマップ" }, "llm_chat": { "placeholder": "メッセージを入力してください…", @@ -2344,6 +2352,9 @@ "processing": "処理中…", "processing_started": "OCR 処理が開始されました。しばらくお待ちいただき、ページを更新してください。", "processing_failed": "OCR 処理の開始に失敗しました", - "view_extracted_text": "抽出されたテキスト(OCR)を表示" + "view_extracted_text": "抽出されたテキスト(OCR)を表示", + "processing_complete": "OCR 処理が完了しました。", + "text_filtered_low_confidence": "OCR は {{confidence}}% の信頼度でテキストを検出しましたが、最小しきい値が {{threshold}}% であるため、破棄されました。", + "open_media_settings": "設定を開く" } } diff --git a/apps/client/src/translations/ko/translation.json b/apps/client/src/translations/ko/translation.json index b0991a87a7..dab39aeb85 100644 --- a/apps/client/src/translations/ko/translation.json +++ b/apps/client/src/translations/ko/translation.json @@ -100,9 +100,6 @@ "no_note_to_delete": "삭제되는 노트가 없습니다 (클론만 삭제됩니다).", "broken_relations_to_be_deleted": "다음 관계가 끊어지고 삭제됩니다({{ relationCount}})", "cancel": "취소", - "ok": "OK", - "deleted_relation_text": "삭제 예정인 노트 {{- note}} (은)는 {{- source}}에서 시작된 관계 {{- relation}}에 의해 참조되고 있습니다.", - "delete_notes_preview": "노트 미리보기 삭제", "close": "닫기", "delete_all_clones_description": "모든 복제본 삭제(최근 변경 사항에서 되돌릴 수 있습니다)" }, diff --git a/apps/client/src/translations/nb-NO/translation.json b/apps/client/src/translations/nb-NO/translation.json index ee36c293fb..9db2e0a1c0 100644 --- a/apps/client/src/translations/nb-NO/translation.json +++ b/apps/client/src/translations/nb-NO/translation.json @@ -39,8 +39,7 @@ }, "delete_notes": { "close": "Lukk", - "cancel": "Avbryt", - "ok": "OK" + "cancel": "Avbryt" }, "export": { "close": "Lukk", diff --git a/apps/client/src/translations/nl/translation.json b/apps/client/src/translations/nl/translation.json index b1dacfd621..09960c30f3 100644 --- a/apps/client/src/translations/nl/translation.json +++ b/apps/client/src/translations/nl/translation.json @@ -21,7 +21,7 @@ }, "bundle-error": { "title": "Custom script laden mislukt", - "message": "Script van notitie met ID \"{{id}}\", getiteld \"{{title}}\" kon niet worden uitgevoerd vanwege:\n\n{{message}}" + "message": "Script voor de notitie met ID \"{{id}}\", getiteld \"{{title}}\" kon niet worden uitgevoerd vanwege:\n\n{{message}}" }, "scripting-error": "Error met script: {{title}}", "widget-list-error": { diff --git a/apps/client/src/translations/pl/translation.json b/apps/client/src/translations/pl/translation.json index 3cd2d35be3..a83b7ae69b 100644 --- a/apps/client/src/translations/pl/translation.json +++ b/apps/client/src/translations/pl/translation.json @@ -78,15 +78,12 @@ "delete_notes": { "cancel": "Anuluj", "close": "Zamknij", - "delete_notes_preview": "Podgląd usuwania notatek", "delete_all_clones_description": "Usuń również wszystkie klony (można cofnąć w oknie Ostatnie zmiany)", "erase_notes_description": "Normalne (miękkie) usuwanie jedynie oznacza notatki jako usunięte i można je przywrócić (w oknie Ostatnie zmiany) przez pewien czas. Zaznaczenie tej opcji spowoduje natychmiastowe wymazanie notatek i nie będzie możliwe ich przywrócenie.", "erase_notes_warning": "Wymaż notatki trwale (nie można cofnąć), w tym wszystkie klony. Wymusi to przeładowanie aplikacji.", "notes_to_be_deleted": "Następujące notatki zostaną usunięte ({{notesCount}})", "no_note_to_delete": "Żadna notatka nie zostanie usunięta (tylko klony).", - "broken_relations_to_be_deleted": "Następujące relacje zostaną zerwane i usunięte ({{ relationCount}})", - "ok": "OK", - "deleted_relation_text": "Notatka {{- note}} (do usunięcia) jest powiązana relacją {{- relation}} pochodzącą z {{- source}}." + "broken_relations_to_be_deleted": "Następujące relacje zostaną zerwane i usunięte ({{ relationCount}})" }, "export": { "close": "Zamknij", @@ -1665,16 +1662,12 @@ "description": "Te opcje dotyczą tylko wersji desktopowych, przeglądarki będą używać własnego natywnego sprawdzania pisowni.", "enable": "Włącz sprawdzanie pisowni", "language_code_label": "Kod(y) języka", - "language_code_placeholder": "na przykład \"pl-PL\", \"en-US\"", - "multiple_languages_info": "Wiele języków można oddzielić przecinkiem, np. \"en-US, de-DE, pl\". ", - "available_language_codes_label": "Dostępne kody języków:", "restart-required": "Zmiany w opcjach sprawdzania pisowni wejdą w życie po ponownym uruchomieniu aplikacji." }, "sync_2": { "config_title": "Konfiguracja synchronizacji", "server_address": "Adres instancji serwera", "timeout": "Limit czasu synchronizacji", - "timeout_unit": "milisekund", "proxy_label": "Serwer proxy synchronizacji (opcjonalnie)", "note": "Uwaga", "note_description": "Jeśli pozostawisz ustawienie proxy puste, zostanie użyte proxy systemowe (dotyczy tylko wersji desktop/electron).", diff --git a/apps/client/src/translations/pt/translation.json b/apps/client/src/translations/pt/translation.json index b28d38e414..1219523ce8 100644 --- a/apps/client/src/translations/pt/translation.json +++ b/apps/client/src/translations/pt/translation.json @@ -88,7 +88,6 @@ "also_delete_note": "Também apagar a nota" }, "delete_notes": { - "delete_notes_preview": "Apagar pré-visualização de notas", "close": "Fechar", "delete_all_clones_description": "Apagar também todos os clones (pode ser desfeito em alterações recentes)", "erase_notes_description": "Apagar normal (suave) apenas marca as notas como apagadas, permitindo que sejam recuperadas (no diálogo de alterações recentes) num período. Se esta opção for marcada, as notas serão apagadas imediatamente e não será possível restaurá-las.", @@ -96,9 +95,7 @@ "notes_to_be_deleted": "As seguintes notas serão apagadas ({{notesCount}})", "no_note_to_delete": "Nenhuma nota será apagada (apenas os clones).", "broken_relations_to_be_deleted": "As seguintes relações serão quebradas e apagadas ({{ relationCount}})", - "cancel": "Cancelar", - "ok": "OK", - "deleted_relation_text": "A nota {{- note}} (a ser apagada) está referenciada pela relação {{- relation}} originada de {{- source}}." + "cancel": "Cancelar" }, "export": { "export_note_title": "Exportar nota", @@ -1435,16 +1432,12 @@ "description": "Estas opções aplicam-se apenas às versões desktop; os navegadores usarão a sua própria verificação ortográfica nativa.", "enable": "Ativar verificação ortográfica", "language_code_label": "Código(s) de idioma", - "language_code_placeholder": "por exemplo \"en-US\", \"de-AT\", \"pt-BR\"", - "multiple_languages_info": "Múltiplos idiomas podem ser separados por vírgula, por exemplo: \"en-US, de-DE, pt-BR, cs\". ", - "available_language_codes_label": "Códigos de idioma disponíveis:", "restart-required": "As alterações nas opções de verificação ortográfica terão efeito após reiniciar a aplicação." }, "sync_2": { "config_title": "Configuração da Sincronização", "server_address": "Endereço da instância do Servidor", "timeout": "Tempo limite da sincronização", - "timeout_unit": "milisegundos", "proxy_label": "Servidor proxy para sincronização (opcional)", "note": "Nota", "note_description": "Se deixar a configuração de proxy em branco, o proxy do sistema será usado (aplica-se apenas à versão desktop/Electron).", diff --git a/apps/client/src/translations/pt_br/translation.json b/apps/client/src/translations/pt_br/translation.json index 24c896984f..fbb7f29d81 100644 --- a/apps/client/src/translations/pt_br/translation.json +++ b/apps/client/src/translations/pt_br/translation.json @@ -94,7 +94,6 @@ "also_delete_note": "Também excluir a nota" }, "delete_notes": { - "delete_notes_preview": "Excluir pré-visualização de notas", "close": "Fechar", "delete_all_clones_description": "Excluir também todos os clones (pode ser desfeito em alterações recentes)", "erase_notes_description": "A exclusão normal (suave) apenas marca as notas como excluídas, permitindo que sejam recuperadas (no diálogo de alterações recentes) dentro de um período de tempo. Se esta opção for marcada, as notas serão apagadas imediatamente e não será possível restaurá-las.", @@ -102,9 +101,7 @@ "notes_to_be_deleted": "As seguintes notas serão excluídas ({{notesCount}})", "no_note_to_delete": "Nenhuma nota será excluída (apenas os clones).", "broken_relations_to_be_deleted": "As seguintes relações serão quebradas e excluídas ({{ relationCount}})", - "cancel": "Cancelar", - "ok": "OK", - "deleted_relation_text": "A nota {{- note}} (a ser excluída) está referenciada pela relação {{- relation}} originada de {{- source}}." + "cancel": "Cancelar" }, "export": { "export_note_title": "Exportar nota", @@ -1944,16 +1941,12 @@ "description": "Estas opções se aplicam apenas às versões desktop; os navegadores usarão sua própria verificação ortográfica nativa.", "enable": "Habilitar verificação ortográfica", "language_code_label": "Código(s) de idioma", - "language_code_placeholder": "por exemplo \"en-US\", \"de-AT\", \"pt-BR\"", - "multiple_languages_info": "Múltiplos idiomas podem ser separados por vírgula, por exemplo: \"en-US, de-DE, pt-BR, cs\". ", - "available_language_codes_label": "Códigos de idioma disponíveis:", "restart-required": "As alterações nas opções de verificação ortográfica terão efeito após reiniciar o aplicativo." }, "sync_2": { "config_title": "Configuração da Sincronização", "server_address": "Endereço da instância do Servidor", "timeout": "Tempo limite da sincronização", - "timeout_unit": "milisegundos", "proxy_label": "Servidor proxy para sincronização (opcional)", "note": "Nota", "note_description": "Se você deixar a configuração de proxy em branco, o proxy do sistema será usado (aplica-se apenas à versão desktop/Electron).", diff --git a/apps/client/src/translations/ro/translation.json b/apps/client/src/translations/ro/translation.json index 6e9d0e2e83..b3006e5b4c 100644 --- a/apps/client/src/translations/ro/translation.json +++ b/apps/client/src/translations/ro/translation.json @@ -459,13 +459,10 @@ "broken_relations_to_be_deleted": "Următoarele relații vor fi întrerupte și șterse ({{ relationCount}})", "cancel": "Anulează", "delete_all_clones_description": "Șterge și toate clonele (se pot recupera în ecranul Schimbări recente)", - "delete_notes_preview": "Previzualizare ștergerea notițelor", "erase_notes_description": "Ștergerea obișnuită doar marchează notițele ca fiind șterse și pot fi recuperate (în ecranul Schimbări recente) pentru o perioadă de timp. Dacă se bifează această opțiune, notițele vor fi șterse imediat fără posibilitatea de a le recupera.", "erase_notes_warning": "Șterge notițele permanent (nu se mai pot recupera), incluzând toate clonele. Va forța reîncărcarea aplicației.", "no_note_to_delete": "Nicio notiță nu va fi ștearsă (doar clonele).", "notes_to_be_deleted": "Următoarele notițe vor fi șterse ({{notesCount}})", - "ok": "OK", - "deleted_relation_text": "Notița {{- note}} ce va fi ștearsă este referențiată de relația {{- relation}}, originând din {{- source}}.", "close": "Închide" }, "delete_relation": { @@ -1237,12 +1234,9 @@ "title": "titlu" }, "spellcheck": { - "available_language_codes_label": "Coduri de limbă disponibile:", "description": "Aceste opțiuni se aplică doar pentru aplicația de desktop, navigatoarele web folosesc propriile corectoare ortografice.", "enable": "Activează corectorul ortografic", "language_code_label": "Codurile de limbă", - "language_code_placeholder": "de exemplu „en-US”, „de-AT”", - "multiple_languages_info": "Mai multe limbi pot fi separate prin virgulă, e.g. \"en-US, de-DE, cs\". ", "title": "Corector ortografic", "restart-required": "Schimbările asupra setărilor corectorului ortografic vor fi aplicate după restartarea aplicației." }, @@ -1269,8 +1263,7 @@ "test_button": "Probează sincronizarea", "test_description": "Această opțiune va testa conexiunea și comunicarea cu serverul de sincronizare. Dacă serverul de sincronizare nu este inițializat, acest lucru va rula și o sincronizare cu documentul local.", "test_title": "Probează sincronizarea", - "timeout": "Timp limită de sincronizare", - "timeout_unit": "milisecunde" + "timeout": "Timp limită de sincronizare" }, "table_of_contents": { "description": "Cuprinsul va apărea în notițele de tip text atunci când notița are un număr de titluri mai mare decât cel definit. Acest număr se poate personaliza:", diff --git a/apps/client/src/translations/ru/translation.json b/apps/client/src/translations/ru/translation.json index 1551ea0f00..093b5b718b 100644 --- a/apps/client/src/translations/ru/translation.json +++ b/apps/client/src/translations/ru/translation.json @@ -83,10 +83,7 @@ "notes_to_be_deleted": "Следующие заметки будут удалены ({{notesCount}})", "no_note_to_delete": "Заметка не будет удалена (только клоны).", "broken_relations_to_be_deleted": "Следующие отношения будут разорваны и удалены ({{relationCount}})", - "cancel": "Отмена", - "ok": "ОК", - "deleted_relation_text": "Примечание {{- note}} (подлежит удалению) ссылается на отношение {{- relation}}, происходящее из {{- source}}.", - "delete_notes_preview": "Предпросмотр удаляемых заметок" + "cancel": "Отмена" }, "database_anonymization": { "light_anonymization_description": "Это действие создаст новую копию базы данных и выполнит её лёгкую анонимизацию — в частности, будет удалён только контент всех заметок, но заголовки и атрибуты останутся. Кроме того, будут сохранены пользовательские заметки, содержащие JavaScript-скрипты frontend/backend и пользовательские виджеты. Это даёт больше контекста для отладки проблем.", @@ -1419,7 +1416,6 @@ "no_results": "Не найдено ярлыков, соответствующих '{{filter}}'" }, "sync_2": { - "timeout_unit": "миллисекунд", "note": "Заметка", "save": "Сохранить", "help": "Помощь", @@ -1679,10 +1675,7 @@ "title": "Проверка орфографии", "enable": "Включить проверку орфографии", "language_code_label": "Код(ы) языков", - "multiple_languages_info": "Несколько языков можно разделять запятой, например, \"en-US, de-DE, cs\". ", - "available_language_codes_label": "Доступные коды языков:", "restart-required": "Изменения параметров проверки орфографии вступят в силу после перезапуска приложения.", - "language_code_placeholder": "например \"en-US\", \"de-AT\"", "description": "Эти параметры применимы только для десктопных сборок, браузеры будут использовать собственную встроенную проверку орфографии." }, "attribute_editor": { diff --git a/apps/client/src/translations/sr/translation.json b/apps/client/src/translations/sr/translation.json index d585852e2f..cf3f0d8681 100644 --- a/apps/client/src/translations/sr/translation.json +++ b/apps/client/src/translations/sr/translation.json @@ -76,7 +76,6 @@ "also_delete_note": "Takođe obriši belešku" }, "delete_notes": { - "delete_notes_preview": "Obriši pregled beleške", "close": "Zatvori", "delete_all_clones_description": "Obriši i sve klonove (može biti poništeno u skorašnjim izmenama)", "erase_notes_description": "Normalno (blago) brisanje samo označava beleške kao obrisane i one mogu biti vraćene (u dijalogu skorašnjih izmena) u određenom vremenskom periodu. Biranje ove opcije će momentalno obrisati beleške i ove beleške neće biti moguće vratiti.", @@ -84,9 +83,7 @@ "notes_to_be_deleted": "Sledeće beleške će biti obrisane ({{- noteCount}})", "no_note_to_delete": "Nijedna beleška neće biti obrisana (samo klonovi).", "broken_relations_to_be_deleted": "Sledeći odnosi će biti prekinuti i obrisani ({{- relationCount}})", - "cancel": "Otkaži", - "ok": "U redu", - "deleted_relation_text": "Beleška {{- note}} (za brisanje) je referencirana sa odnosom {{- relation}} koji potiče iz {{- source}}." + "cancel": "Otkaži" }, "export": { "export_note_title": "Izvezi belešku", diff --git a/apps/client/src/translations/tr/translation.json b/apps/client/src/translations/tr/translation.json index 2f534ba12e..1c0198d3c0 100644 --- a/apps/client/src/translations/tr/translation.json +++ b/apps/client/src/translations/tr/translation.json @@ -21,12 +21,32 @@ }, "delete_notes": { "close": "Kapat", - "delete_notes_preview": "Not önizlemesini sil", "delete_all_clones_description": "Tüm klonları da sil (son değişikliklerden geri alınabilir)", - "erase_notes_description": "Normal (yazılımsal) silme işlemi, notları yalnızca silinmiş olarak işaretler ve belirli bir süre içinde (son değişiklikler iletişim kutusunda) geri alınabilir. Bu seçeneği işaretlemek, notları hemen siler ve notların geri alınması mümkün olmaz." + "erase_notes_description": "Normal (yazılımsal) silme işlemi, notları yalnızca silinmiş olarak işaretler ve belirli bir süre içinde (son değişiklikler iletişim kutusunda) geri alınabilir. Bu seçeneği işaretlemek, notları hemen siler ve notların geri alınması mümkün olmaz.", + "erase_notes_warning": "Notları, tüm kopyaları da dahil olmak üzere kalıcı olarak silin (geri alınamaz). Bu işlem, uygulamanın yeniden yüklenmesine neden olacaktır.", + "notes_to_be_deleted": "Aşağıdaki notlar silinecektir. ({{notesCount}})", + "no_note_to_delete": "Hiçbir not silinmeyecek (sadece kopyaları silinecek).", + "broken_relations_to_be_deleted": "Aşağıdaki ilişkiler koparılacak ve silinecektir ({{ relationCount}})", + "cancel": "İptal" }, "export": { - "close": "Kapat" + "close": "Kapat", + "export_note_title": "Notu dışa aktar", + "export_type_subtree": "Bu not ve tüm torunları", + "format_html": "HTML - tüm biçimlendirmeyi koruduğu için önerilir", + "format_html_zip": "ZIP arşivindeki HTML dosyaları - tüm biçimlendirmeyi koruduğu için bu yöntem önerilir.", + "format_markdown": "Markdown - bu, biçimlendirmenin büyük kısmını korur.", + "format_opml": "OPML - yalnızca metin için anahat değişim biçimi. Biçimlendirme, resimler ve dosyalar dahil edilmez.", + "opml_version_1": "OPML v1.0 - yalnızca düz metin", + "opml_version_2": "OPML v2.0 - HTML de destekler", + "export_type_single": "Yalnızca bu not, alt öğeleri olmadan", + "export": "Dışa aktar", + "choose_export_type": "Lütfen önce dışa aktarma türünü seçin", + "export_status": "Dışa aktarma durumu", + "export_in_progress": "Dışa aktarma devam ediyor: {{progressCount}}", + "export_finished_successfully": "Dışa aktarma başarıyla tamamlandı.", + "format_pdf": "PDF - yazdırma veya paylaşım amaçları için.", + "share-format": "Web yayını için HTML - paylaşılan notlarda kullanılan temayı kullanır, ancak statik bir web sitesi olarak yayınlanabilir." }, "import": { "chooseImportFile": "İçe aktarım dosyası", @@ -58,7 +78,9 @@ "widget-render-error": { "title": "Özel React widget'ı çizilirken sorun yaşandı" }, - "scripting-error": "Kullanıcı tanımlı betik hatası: {{title}}" + "scripting-error": "Kullanıcı tanımlı betik hatası: {{title}}", + "widget-missing-parent": "Özel widget'ın zorunlu '{{property}}' özelliği tanımlanmamıştır.\n\nBu komut dosyasının bir kullanıcı arayüzü öğesi olmadan çalıştırılması gerekiyorsa, bunun yerine '#run=frontendStartup' kullanın.", + "open-script-note": "Komut dosyası notunu aç" }, "add_link": { "add_link": "Bağlantı ekle", @@ -103,5 +125,32 @@ "are_you_sure_remove_note": "\"{{title}}\" notunu ilişki haritasından kaldırmak istediğinize emin misiniz?. ", "also_delete_note": "Notu da sil", "if_you_dont_check": "Bunu işaretlemezseniz, not yalnızca ilişki haritasından kaldırılacaktır." + }, + "help": { + "title": "Özet tablo", + "editShortcuts": "Klavye kısayollarını düzenle", + "noteNavigation": "Not içinde gezinme", + "goUpDown": "Notlar listesinde yukarı/aşağı gitmek", + "collapseExpand": "düğümü daralt/genişlet", + "notSet": "ayarlanmamış", + "goBackForwards": "tarihte geri/ileri git", + "showJumpToNoteDialog": "\"Şuraya Git\" iletişim kutusunu göster", + "scrollToActiveNote": "Aktif nota kaydır", + "jumpToParentNote": "Üst nota git", + "collapseWholeTree": "Tüm not ağacını daralt", + "collapseSubTree": "Alt ağacı daralt", + "tabShortcuts": "Sekme kısayolları", + "newTabNoteLink": "Not bağlantısı notu yeni sekmede açılır", + "newTabWithActivationNoteLink": "Not bağlantısına tıklandığında not yeni bir sekmede açılır ve etkinleştirilir", + "onlyInDesktop": "Yalnızca masaüstünde (Electron derlemesi)", + "openEmptyTab": "boş sekmeyi aç", + "closeActiveTab": "aktif sekmeyi kapat", + "activateNextTab": "sonraki sekmeyi etkinleştir", + "activatePreviousTab": "önceki sekmeyi etkinleştir", + "creatingNotes": "Not oluşturma", + "createNoteAfter": "etkin nottan sonra yeni not oluşturma", + "createNoteInto": "aktif nota yeni bir alt not oluşturun", + "editBranchPrefix": "prefix değerini aktif not klonunun düzenle", + "movingCloningNotes": "Notları taşıma / klonlama" } } diff --git a/apps/client/src/translations/tw/translation.json b/apps/client/src/translations/tw/translation.json index 35c8dbff1b..a8af023d71 100644 --- a/apps/client/src/translations/tw/translation.json +++ b/apps/client/src/translations/tw/translation.json @@ -88,7 +88,6 @@ "also_delete_note": "同時刪除筆記" }, "delete_notes": { - "delete_notes_preview": "刪除筆記預覽", "delete_all_clones_description": "同時刪除所有克隆(可以在最近修改中撤消)", "erase_notes_description": "通常(軟)刪除僅標記筆記為已刪除,可以在一段時間內透過最近修改對話方塊撤消。勾選此選項將立即擦除筆記,無法撤銷。", "erase_notes_warning": "永久擦除筆記(無法撤銷),包括所有克隆。這將強制應用程式重新載入。", @@ -96,8 +95,6 @@ "no_note_to_delete": "沒有筆記將被刪除(僅克隆)。", "broken_relations_to_be_deleted": "將刪除以下關聯並斷開連接 ({{ relationCount}})", "cancel": "取消", - "ok": "確定", - "deleted_relation_text": "筆記 {{- note}}(將被刪除的筆記)被以下關聯 {{- relation}} 引用,來自 {{- source}}。", "close": "關閉" }, "export": { @@ -368,7 +365,7 @@ "calendar_root": "標記應用作為每日筆記的根。只應標記一個筆記。", "archived": "含有此標籤的筆記預設在搜尋結果中不可見(也適用於跳轉至、新增連結對話方塊等)。", "exclude_from_export": "筆記(及其子階層)不會包含在任何匯出的筆記中", - "run": "定義腳本應運行的事件。可能的值包括:\n
    \n
  • frontendStartup - Trilium前端啟動時(或重新整理時),但不會在移動端執行。
  • \n
  • mobileStartup - Trilium前端啟動時(或重新整理時), 在行動端會執行。
  • \n
  • backendStartup - Trilium後端啟動時
  • \n
  • hourly - 每小時運行一次。您可以使用附加標籤runAtHour指定小時。
  • \n
  • daily - 每天運行一次
  • \n
", + "run": "定義腳本應運行的事件。可能的值包括:\n
    \n
  • frontendStartup - Trilium前端啟動時(或重新整理時),但不會在移動端執行。
  • \n
  • mobileStartup - Trilium前端啟動時(或重新整理時), 在行動端會執行。
  • \n
  • backendStartup - Trilium後端啟動時。
  • \n
  • hourly - 每小時運行一次。您可以使用附加標籤runAtHour指定小時。
  • \n
  • daily - 每天運行一次。
  • \n
", "run_on_instance": "定義應在哪個 Trilium 實例上運行。預設為所有實例。", "run_at_hour": "應在哪個小時運行。應與#run=hourly一起使用。可以多次定義,以便一天內運行多次。", "disable_inclusion": "含有此標籤的腳本不會包含在父腳本執行中。", @@ -706,7 +703,8 @@ "export_as_image": "匯出為圖片", "export_as_image_png": "PNG (點陣)", "export_as_image_svg": "SVG (向量)", - "note_map": "筆記地圖" + "note_map": "筆記地圖", + "view_ocr_text": "顯示 OCR 文字" }, "onclick_button": { "no_click_handler": "按鈕元件'{{componentId}}'沒有定義點擊時的處理方式" @@ -802,7 +800,10 @@ "expand_first_level": "展開直接子級", "expand_nth_level": "展開 {{depth}} 層", "expand_all_levels": "展開所有層級", - "hide_child_notes": "隱藏樹中的子筆記" + "hide_child_notes": "隱藏樹中的子筆記", + "open_all_in_tabs": "全部打開", + "open_all_in_tabs_tooltip": "在新分頁中開啟所有結果", + "open_all_confirm": "這將在新分頁中開啟 {{count}} 則筆記。要繼續嗎?" }, "edited_notes": { "no_edited_notes_found": "今天還沒有編輯過的筆記...", @@ -856,7 +857,8 @@ "collapse": "收摺到正常大小", "title": "筆記地圖", "fix-nodes": "固定節點", - "link-distance": "連結距離" + "link-distance": "連結距離", + "too-many-notes": "此子樹包含 {{count}} 則筆記,已超過筆記地圖中可顯示的 {{max}} 則上限。" }, "note_paths": { "title": "筆記路徑", @@ -1061,7 +1063,8 @@ "note_already_in_diagram": "筆記 \"{{title}}\" 已經在圖中。", "enter_title_of_new_note": "輸入新筆記的標題", "default_new_note_title": "新筆記", - "click_on_canvas_to_place_new_note": "點擊畫布以放置新筆記" + "click_on_canvas_to_place_new_note": "點擊畫布以放置新筆記", + "rename_relation": "重新命名關聯" }, "backend_log": { "refresh": "重新整理" @@ -1196,12 +1199,28 @@ }, "images": { "images_section_title": "圖片", - "download_images_automatically": "自動下載圖片以供離線使用。", - "download_images_description": "貼上的 HTML 可能包含線上圖片的引用,Trilium 會找到這些引用並下載圖片,以便它們可以離線使用。", - "enable_image_compression": "啟用圖片壓縮", - "max_image_dimensions": "圖片的最大寬度 / 高度(超過此限制的圖片將會被縮放)。", - "jpeg_quality_description": "JPEG 質量(10 - 最差質量,100 最佳質量,建議為 50 - 85)", - "max_image_dimensions_unit": "像素" + "download_images_automatically": "自動下載圖片", + "download_images_description": "從貼上的 HTML 下載引用的線上圖片以便離線使用。", + "enable_image_compression": "圖片壓縮", + "max_image_dimensions": "最大圖片尺寸", + "jpeg_quality_description": "建議範圍為 50–85。較低的數值可縮小檔案大小,較高的數值則能保留更多細節。", + "max_image_dimensions_unit": "像素", + "enable_image_compression_description": "在上傳或貼上圖片時壓縮並調整圖片大小。", + "max_image_dimensions_description": "超過此尺寸的圖片將會自動調整大小。", + "jpeg_quality": "JPEG 品質", + "ocr_section_title": "文字擷取(OCR)", + "ocr_related_content_languages": "內容語言(用於文字擷取)", + "ocr_auto_process": "自動處理新檔案", + "ocr_auto_process_description": "自動從新上傳或貼上的檔案中擷取文字。", + "ocr_min_confidence": "最低信賴度", + "ocr_confidence_description": "僅提取高於此信賴度閾值的文字。較低的閾值雖能包含更多文字,但準確度可能較低。", + "batch_ocr_title": "處理現有檔案", + "batch_ocr_description": "從筆記中的所有現有圖片、PDF 檔案及 Office 文件中擷取文字。根據檔案數量多寡,此過程可能需要一些時間。", + "batch_ocr_start": "開始批次處理", + "batch_ocr_starting": "開始批次處理…", + "batch_ocr_progress": "正在處理 {{processed}} 個檔案,共 {{total}} 個檔案…", + "batch_ocr_completed": "批次處理完成!已處理 {{processed}} 個檔案。", + "batch_ocr_error": "批次處理期間發生錯誤:{{error}}" }, "attachment_erasure_timeout": { "attachment_erasure_timeout": "附件清理超時", @@ -1314,7 +1333,8 @@ "date-and-time": "日期和時間", "path": "路徑", "database_backed_up_to": "資料庫已備份至 {{backupFilePath}}", - "no_backup_yet": "尚無備份" + "no_backup_yet": "尚無備份", + "download": "下載" }, "etapi": { "title": "ETAPI", @@ -1379,12 +1399,15 @@ "spellcheck": { "title": "拼寫檢查", "description": "這些選項僅適用於桌面版,瀏覽器將使用其原生的拼寫檢查功能。", - "enable": "啟用拼寫檢查", - "language_code_label": "語言代碼", - "language_code_placeholder": "例如 \"en-US\", \"de-AT\"", - "multiple_languages_info": "多種語言可以用逗號分隔,例如 \"en-US, de-DE, cs\"。 ", - "available_language_codes_label": "可用的語言代碼:", - "restart-required": "拼寫檢查選項的更改將在應用重啟後生效。" + "enable": "拼寫檢查", + "language_code_label": "拼寫檢查語言", + "restart-required": "拼寫檢查選項的更改將在應用重啟後生效。", + "custom_dictionary_title": "自訂字典", + "custom_dictionary_description": "新增至字典的詞彙會同步至您所有的裝置。", + "custom_dictionary_edit": "自訂詞彙", + "custom_dictionary_edit_description": "編輯拼寫檢查器不應標記的詞彙清單。變更將於重新啟動後生效。", + "custom_dictionary_open": "編輯字典", + "related_description": "設定拼寫檢查語言及自訂字典。" }, "sync_2": { "config_title": "同步設定", @@ -1400,7 +1423,7 @@ "test_description": "測試和同步伺服器之間的連接。如果同步伺服器沒有初始化,這會將本地文件同步至同步伺服器上。", "test_button": "測試同步", "handshake_failed": "同步伺服器握手失敗,錯誤:{{message}}", - "timeout_unit": "毫秒" + "timeout_description": "在放棄慢速同步連線前應等待多久。若網路不穩定,請延長等待時間。" }, "api_log": { "close": "關閉" @@ -1497,7 +1520,8 @@ "new-feature": "新增", "collections": "集合", "ai-chat": "AI 聊天", - "spreadsheet": "試算表" + "spreadsheet": "試算表", + "llm-chat": "AI 對話" }, "protect_note": { "toggle-on": "保護筆記", @@ -1866,7 +1890,7 @@ }, "content_language": { "title": "內文語言", - "description": "選擇一種或多種語言作為唯讀或可編輯文字筆記的可選基本屬性,這將支援拼寫檢查或從右向左之類的功能。" + "description": "選擇一種或多種語言作為唯讀或可編輯文字筆記的可選基本屬性,這將支援拼寫檢查、從右向左及文字擷取 (OCR) 等功能。" }, "switch_layout_button": { "title_vertical": "將編輯面板移至底部", @@ -2046,7 +2070,9 @@ "title": "實驗性選項", "disclaimer": "這些選項屬實驗性質,可能導致系統不穩定。請謹慎使用。", "new_layout_name": "新版面配置", - "new_layout_description": "體驗全新版面配置,呈現更現代的外觀與更佳的使用體驗。在未來版本將進行大幅調整。" + "new_layout_description": "體驗全新版面配置,呈現更現代的外觀與更佳的使用體驗。在未來版本將進行大幅調整。", + "llm_name": "AI / LLM 對話", + "llm_description": "啟用由大語言模型驅動的 AI 聊天側邊欄及 LLM 聊天筆記。" }, "server": { "unknown_http_error_title": "與伺服器通訊錯誤", @@ -2229,6 +2255,121 @@ "sample_user_journey": "使用者旅程", "sample_xy": "XY 圖表", "sample_venn": "韋恩圖", - "sample_ishikawa": "魚骨圖" + "sample_ishikawa": "魚骨圖", + "sample_treeview": "樹狀視圖", + "sample_wardley": "沃德利地圖" + }, + "llm_chat": { + "placeholder": "輸入訊息…", + "send": "送出", + "sending": "正在送出…", + "empty_state": "請在下方輸入訊息,開啟對話。", + "searching_web": "正在搜尋網頁…", + "web_search": "網頁搜尋", + "note_tools": "筆記存取", + "sources": "來源", + "sources_summary": "來自 {{sites}} 個網站的 {{count}} 個來源", + "extended_thinking": "延伸思考", + "legacy_models": "傳統模型", + "thinking": "正在思考…", + "thought_process": "思考過程", + "tool_calls": "{{count}} 次工具調用", + "input": "輸入", + "result": "結果", + "error": "錯誤", + "tool_error": "失敗", + "total_tokens": "{{total}} 個詞元", + "tokens_detail": "{{prompt}} 提示詞 + {{completion}} 補全", + "tokens_used": "{{prompt}} 提示詞 + {{completion}} 補全 = {{total}} 個詞元", + "tokens_used_with_cost": "{{prompt}} 提示詞 + {{completion}} 補全 = {{total}} 個詞元(約 ${{cost}})", + "tokens_used_with_model": "{{model}}:{{prompt}} 提示詞 + {{completion}} 補全 = {{total}} 個詞元", + "tokens_used_with_model_and_cost": "{{model}}:{{prompt}} 提示詞 + {{completion}} 補全 = {{total}} 個詞元(約 ${{cost}})", + "tokens": "詞元", + "context_used": "已使用 {{percentage}}%", + "note_context_enabled": "點擊以禁用筆記上下文:{{title}}", + "note_context_disabled": "點擊將當前筆記納入上下文", + "no_provider_message": "尚未設定任何 AI 服務提供者。請新增一個以開始聊天。", + "add_provider": "新增 AI 提供者" + }, + "ocr": { + "processing_complete": "OCR 處理已完成。", + "processing_failed": "無法啟動 OCR 處理", + "text_filtered_low_confidence": "OCR 偵測到的文字信賴度為 {{confidence}}%,但因您的最低閾值設定為 {{threshold}}%,故該結果已被捨棄。", + "open_media_settings": "開啟設定", + "view_extracted_text": "檢視擷取的文字 (OCR)", + "extracted_text": "已擷取的文字 (OCR)", + "extracted_text_title": "已擷取的文字 (OCR)", + "loading_text": "正在載入 OCR 文字…", + "no_text_available": "無 OCR 文字可用", + "no_text_explanation": "此筆記尚未經過 OCR 文字擷取處理,或未找到任何文字。", + "failed_to_load": "載入 OCR 文字失敗", + "process_now": "處理 OCR", + "processing": "正在處理…", + "processing_started": "OCR 處理已開始。請稍候片刻並重新整理頁面。" + }, + "mind-map": { + "addChild": "新增子節點", + "addParent": "新增父節點", + "addSibling": "新增同級節點", + "removeNode": "刪除節點", + "focus": "專注模式", + "cancelFocus": "退出專注模式", + "moveUp": "上移", + "moveDown": "下移", + "link": "連結", + "linkBidirectional": "雙向連結", + "clickTips": "請點擊目標節點", + "summary": "摘要" + }, + "llm": { + "settings_title": "AI / LLM", + "settings_description": "設定 AI 及大型語言模型整合。", + "feature_not_enabled": "請前往「設定」→「進階」→「實驗性功能」啟用 LLM 實驗性功能,即可使用 AI 整合。", + "add_provider": "新增提供者", + "add_provider_title": "新增 AI 提供者", + "configured_providers": "已設定的提供者", + "no_providers_configured": "尚未設定任何提供者。", + "provider_name": "名稱", + "provider_type": "提供者", + "actions": "動作", + "delete_provider": "刪除", + "delete_provider_confirmation": "您確定要刪除提供者 \"{{name}}\" 嗎?", + "api_key": "API 金鑰", + "api_key_placeholder": "請輸入您的 API 金鑰", + "cancel": "取消", + "mcp_title": "MCP(模型上下文協定)", + "mcp_enabled": "MCP 伺服器", + "mcp_enabled_description": "公開一個模型上下文協定 (MCP) 端點,以便人工智慧編程助手(例如 Claude Code、GitHub Copilot)能夠讀取並修改您的筆記。此端點僅限從 localhost 存取。", + "mcp_endpoint_title": "端點網址", + "mcp_endpoint_description": "將此網址新增至您的 AI 助理的 MCP 設定中", + "tools": { + "search_notes": "搜尋筆記", + "get_note": "取得筆記", + "get_note_content": "取得筆記內容", + "update_note_content": "更新筆記內容", + "append_to_note": "追加至筆記", + "create_note": "建立筆記", + "get_attributes": "取得屬性", + "get_attribute": "取得屬性", + "set_attribute": "設定屬性", + "delete_attribute": "移除屬性", + "get_child_notes": "取得子筆記", + "get_subtree": "取得子階層", + "load_skill": "載入技能", + "web_search": "網頁搜尋", + "note_in_parent": "", + "get_attachment": "取得附件", + "get_attachment_content": "讀取附件內容" + } + }, + "sidebar_chat": { + "title": "AI 對話", + "launcher_title": "打開 AI 對話", + "new_chat": "開始新對話", + "save_chat": "將對話保存至筆記", + "empty_state": "開始會話", + "history": "對話歷史", + "recent_chats": "最近的對話", + "no_chats": "無先前的對話記錄" } } diff --git a/apps/client/src/translations/uk/translation.json b/apps/client/src/translations/uk/translation.json index 75c890ffbf..d1d851e2fd 100644 --- a/apps/client/src/translations/uk/translation.json +++ b/apps/client/src/translations/uk/translation.json @@ -186,7 +186,6 @@ "also_delete_note": "Також видалити нотатку" }, "delete_notes": { - "delete_notes_preview": "Видалити попередній перегляд нотаток", "close": "Закрити", "delete_all_clones_description": "Видалити також усі клони (можна скасувати в останніх змінах)", "erase_notes_description": "Звичайне (м’яке) видалення лише позначає нотатки як видалені і їх можна відновити (у діалоговому вікні останніх змін) протягом певного періоду часу. Якщо позначити цю опцію, нотатки будуть видалені негайно і їх неможливо буде відновити.", @@ -194,9 +193,7 @@ "notes_to_be_deleted": "Наступні нотатки будуть видалені ({{notesCount}})", "no_note_to_delete": "Жодну нотатку не буде видалено (лише клони).", "broken_relations_to_be_deleted": "Наступні зв'язки будуть розірвані та видалені ({{ relationCount}})", - "cancel": "Скасувати", - "ok": "ОК", - "deleted_relation_text": "Нотатка {{- note}} (буде видалена) посилається на зв'язок {{- relation}}, що походить з {{- source}}." + "cancel": "Скасувати" }, "export": { "export_note_title": "Експорт нотатки", @@ -1744,16 +1741,12 @@ "description": "Ці параметри застосовуються лише для збірок для ПК, браузери використовуватимуть власну вбудовану перевірку орфографії.", "enable": "Увімкнути перевірку орфографії", "language_code_label": "Код(и) мови", - "language_code_placeholder": "наприклад, \"en-US\", \"de-AT\"", - "multiple_languages_info": "Кілька мов можна розділяти комами, наприклад, \"en-US, de-DE, cs\". ", - "available_language_codes_label": "Доступні коди мови:", "restart-required": "Зміни в параметрах перевірки орфографії набудуть чинності після перезапуску програми." }, "sync_2": { "config_title": "Конфігурація синхронізації", "server_address": "Адреса екземпляра сервера", "timeout": "Тайм-аут синхронізації", - "timeout_unit": "мілісекунди", "proxy_label": "Синхронізація проксі-сервера (необов'язково)", "note": "Нотатка", "note_description": "Якщо залишити налаштування проксі-сервера порожнім, буде використано системний проксі-сервер (стосується лише збірки для ПК/електронної версії).", diff --git a/apps/client/src/translations/vi/translation.json b/apps/client/src/translations/vi/translation.json index 022262c9f1..76b4418204 100644 --- a/apps/client/src/translations/vi/translation.json +++ b/apps/client/src/translations/vi/translation.json @@ -27,7 +27,6 @@ }, "delete_notes": { "close": "Đóng", - "ok": "OK", "cancel": "Huỷ" }, "export": { diff --git a/apps/client/src/types-lib.d.ts b/apps/client/src/types-lib.d.ts index 4f942b8cb6..8d3c9296d1 100644 --- a/apps/client/src/types-lib.d.ts +++ b/apps/client/src/types-lib.d.ts @@ -66,6 +66,7 @@ declare module "preact" { interface ElectronWebViewElement extends JSX.HTMLAttributes { src: string; class: string; + key?: string | number; } interface IntrinsicElements { diff --git a/apps/client/src/types.d.ts b/apps/client/src/types.d.ts index f7673901c1..6e2196eab9 100644 --- a/apps/client/src/types.d.ts +++ b/apps/client/src/types.d.ts @@ -24,6 +24,7 @@ interface CustomGlobals { getReferenceLinkTitle: (href: string) => Promise; getReferenceLinkTitleSync: (href: string) => string; getActiveContextNote: () => FNote | null; + getThemeStyle: () => "auto" | "light" | "dark"; ESLINT: Library; appContext: AppContext; froca: Froca; @@ -51,8 +52,9 @@ interface CustomGlobals { isElectron: boolean; isRtl: boolean; iconRegistry: IconRegistry; - themeCssUrl: string; - themeUseNextAsBase?: "next" | "next-light" | "next-dark"; + theme: string; + themeBase?: "next" | "next-light" | "next-dark"; + customThemeCssUrl?: string; iconPackCss: string; headingStyle: "plain" | "underline" | "markdown"; layoutOrientation: "vertical" | "horizontal"; diff --git a/apps/client/src/widgets/attribute_widgets/UserAttributesList.tsx b/apps/client/src/widgets/attribute_widgets/UserAttributesList.tsx index f01e70b491..4ebcab4813 100644 --- a/apps/client/src/widgets/attribute_widgets/UserAttributesList.tsx +++ b/apps/client/src/widgets/attribute_widgets/UserAttributesList.tsx @@ -87,7 +87,7 @@ function buildUserAttribute(attr: AttributeWithDefinitions): ComponentChildren { content = <>{" "}{attr.friendlyName}; break; case "url": - content = {attr.friendlyName}; + content = e.stopPropagation()}>{attr.friendlyName}; break; case "color": style = { backgroundColor: value, color: getReadableTextColor(value) }; diff --git a/apps/client/src/widgets/collections/NoteList.tsx b/apps/client/src/widgets/collections/NoteList.tsx index 0c37c4a08a..038d90a052 100644 --- a/apps/client/src/widgets/collections/NoteList.tsx +++ b/apps/client/src/widgets/collections/NoteList.tsx @@ -180,11 +180,13 @@ export function useNoteIds(note: FNote | null | undefined, viewType: ViewTypeOpt // Refresh on alterations to the note subtree. useTriliumEvent("entitiesReloaded", ({ loadResults }) => { - if (note && loadResults.getBranchRows().some(branch => - branch.parentNoteId === note.noteId - || noteIds.includes(branch.parentNoteId ?? "")) + if (note && ( + loadResults.getNoteReorderings().includes(note.noteId) + || loadResults.getBranchRows().some(branch => + branch.parentNoteId === note.noteId + || noteIds.includes(branch.parentNoteId ?? "")) || loadResults.getAttributeRows().some(attr => attr.name === "archived" && attr.noteId && noteIds.includes(attr.noteId)) - ) { + )) { refreshNoteIds(); } }); diff --git a/apps/client/src/widgets/collections/board/data.spec.ts b/apps/client/src/widgets/collections/board/data.spec.ts index b8f0f50341..316efbcba2 100644 --- a/apps/client/src/widgets/collections/board/data.spec.ts +++ b/apps/client/src/widgets/collections/board/data.spec.ts @@ -27,7 +27,7 @@ describe("Board data", () => { froca.branches["note1_note2"] = branch; froca.getNoteFromCache("note1")!.addChild("note2", "note1_note2", false); const data = await getBoardData(parentNote, "status", {}, false); - const noteIds = Array.from(data.byColumn.values()).flat().map(item => item.note.noteId); + const noteIds = [...data.byColumn.values()].flat().map(item => item.note.noteId); expect(noteIds.length).toBe(3); }); }); diff --git a/apps/client/src/widgets/collections/calendar/event_builder.ts b/apps/client/src/widgets/collections/calendar/event_builder.ts index dec64feee8..fd0ce3bbb2 100644 --- a/apps/client/src/widgets/collections/calendar/event_builder.ts +++ b/apps/client/src/widgets/collections/calendar/event_builder.ts @@ -75,7 +75,7 @@ export async function buildEventsForCalendar(note: FNote, e: EventSourceFuncArg) if (dateNote.hasChildren()) { - const childNoteIds = await dateNote.getSubtreeNoteIds(); + const childNoteIds = dateNote.getChildNoteIds(); for (const childNoteId of childNoteIds) { childNoteToDateMapping[childNoteId] = startDate; } diff --git a/apps/client/src/widgets/collections/calendar/index.css b/apps/client/src/widgets/collections/calendar/index.css index df93910b50..51ff05e032 100644 --- a/apps/client/src/widgets/collections/calendar/index.css +++ b/apps/client/src/widgets/collections/calendar/index.css @@ -1,20 +1,9 @@ -:root { - /* Default values to be overridden by themes */ - --calendar-coll-event-background-lightness: 95%; - --calendar-coll-event-background-saturation: 80%; - --calendar-coll-event-background-color: var(--accented-background-color); - --calendar-coll-event-text-color: var(--main-text-color); - --calendar-coll-event-hover-filter: none; - --callendar-coll-event-archived-sripe-color: #00000013; - --calendar-coll-today-background-color: var(--more-accented-background-color); -} - .calendar-view { - --fc-event-border-color: var(--calendar-coll-event-text-color); - --fc-event-bg-color: var(--calendar-coll-event-background-color); - --fc-event-text-color: var(--calendar-coll-event-text-color); + --fc-event-border-color: var(--calendar-coll-event-text-color, var(--main-text-color)); + --fc-event-bg-color: var(--calendar-coll-event-background-color, var(--accented-background-color)); + --fc-event-text-color: var(--calendar-coll-event-text-color, var(--main-text-color)); --fc-event-selected-overlay-color: transparent; - --fc-today-bg-color: var(--calendar-coll-today-background-color); + --fc-today-bg-color: var(--calendar-coll-today-background-color, var(--more-accented-background-color)); overflow: hidden; position: relative; @@ -123,7 +112,7 @@ z-index: -1; --c1: transparent; - --c2: var(--callendar-coll-event-archived-sripe-color); + --c2: var(--callendar-coll-event-archived-sripe-color, #00000013); background: repeating-linear-gradient(45deg, var(--c1), var(--c1) 8px, var(--c2) 8px, var(--c2) 16px); @@ -153,8 +142,8 @@ --fc-event-text-color: var(--custom-color); --fc-event-bg-color: hsl(var(--custom-color-hue), - var(--calendar-coll-event-background-saturation), - var(--calendar-coll-event-background-lightness)) !important; + var(--calendar-coll-event-background-saturation, 80%), + var(--calendar-coll-event-background-lightness, 95%)) !important; } .calendar-view a.fc-timegrid-event:focus-visible, @@ -171,7 +160,7 @@ .calendar-view a.fc-timegrid-event:hover, .calendar-view a.fc-daygrid-event:hover { - filter: var(--calendar-coll-event-hover-filter); + filter: var(--calendar-coll-event-hover-filter, none); border-color: var(--fc-event-text-color); text-decoration: none; color: currentColor; diff --git a/apps/client/src/widgets/collections/calendar/index.tsx b/apps/client/src/widgets/collections/calendar/index.tsx index 349d666e6c..4594d64564 100644 --- a/apps/client/src/widgets/collections/calendar/index.tsx +++ b/apps/client/src/widgets/collections/calendar/index.tsx @@ -82,6 +82,7 @@ export const LOCALE_MAPPINGS: Record Promise<{ de hi: () => import("@fullcalendar/core/locales/hi"), ga: null, cn: () => import("@fullcalendar/core/locales/zh-cn"), + cs: () => import("@fullcalendar/core/locales/cs"), tw: () => import("@fullcalendar/core/locales/zh-tw"), ro: () => import("@fullcalendar/core/locales/ro"), ru: () => import("@fullcalendar/core/locales/ru"), @@ -143,7 +144,12 @@ export default function CalendarView({ note, noteIds }: ViewModeProps { + // Only process actual date/time changes, not other property changes (e.g., title via setProp). + const datesChanged = e.oldEvent.start?.getTime() !== e.event.start?.getTime() + || e.oldEvent.end?.getTime() !== e.event.end?.getTime() + || e.oldEvent.allDay !== e.event.allDay; + if (!datesChanged) return; + const { startDate, endDate } = parseStartEndDateFromEvent(e.event); if (!startDate) return; diff --git a/apps/client/src/widgets/collections/table/row_editing.ts b/apps/client/src/widgets/collections/table/row_editing.ts index c4df69e7ae..03f6b8ff49 100644 --- a/apps/client/src/widgets/collections/table/row_editing.ts +++ b/apps/client/src/widgets/collections/table/row_editing.ts @@ -51,6 +51,8 @@ export default function useRowTableEditing(api: RefObject, attributeD if (type === "labels") { if (typeof newValue === "boolean") { newValue = newValue ? "true" : "false"; + } else if (typeof newValue === "number") { + newValue = String(newValue); } setLabel(noteId, name, newValue); } else if (type === "relations") { diff --git a/apps/client/src/widgets/dialogs/delete_notes.css b/apps/client/src/widgets/dialogs/delete_notes.css new file mode 100644 index 0000000000..864fcc2e0c --- /dev/null +++ b/apps/client/src/widgets/dialogs/delete_notes.css @@ -0,0 +1,30 @@ +.delete-notes-dialog .tn-card { + margin-bottom: 16px; +} + +.delete-notes-dialog .tn-card:last-child { + margin-bottom: 0; +} + +.delete-notes-dialog .preview-list { + margin: 0; + padding: 0; + list-style: none; + max-height: 200px; + overflow: auto; +} + +.delete-notes-dialog .preview-list li { + padding: 6px 16px; + border-bottom: 1px solid var(--main-border-color); +} + +.delete-notes-dialog .preview-list li:last-child { + border-bottom: none; +} + +.delete-notes-dialog .preview-list small { + margin-inline-start: 8px; + font-size: 0.8em; + color: var(--muted-text-color); +} diff --git a/apps/client/src/widgets/dialogs/delete_notes.tsx b/apps/client/src/widgets/dialogs/delete_notes.tsx index c58d440b72..2a5cb0c0b5 100644 --- a/apps/client/src/widgets/dialogs/delete_notes.tsx +++ b/apps/client/src/widgets/dialogs/delete_notes.tsx @@ -1,15 +1,22 @@ -import { useRef, useState, useEffect } from "preact/hooks"; -import { t } from "../../services/i18n.js"; -import FormCheckbox from "../react/FormCheckbox.js"; -import Modal from "../react/Modal.js"; +import "./delete_notes.css"; + import type { DeleteNotesPreview } from "@triliumnext/commons"; -import server from "../../services/server.js"; +import { useEffect, useRef, useState } from "preact/hooks"; + import froca from "../../services/froca.js"; -import FNote from "../../entities/fnote.js"; -import link from "../../services/link.js"; +import { t } from "../../services/i18n.js"; +import server from "../../services/server.js"; import Button from "../react/Button.jsx"; -import Alert from "../react/Alert.jsx"; +import { Card, CardSection } from "../react/Card.js"; +import FormToggle from "../react/FormToggle.js"; import { useTriliumEvent } from "../react/hooks.jsx"; +import Modal from "../react/Modal.js"; +import NoteLink from "../react/NoteLink.js"; +import OptionsRow from "../type_widgets/options/components/OptionsRow.js"; + +interface CloneInfo { + totalCloneCount: number; +} export interface ResolveOptions { proceed: boolean; @@ -24,9 +31,9 @@ interface ShowDeleteNotesDialogOpts { } interface BrokenRelationData { - note: string; - relation: string; - source: string; + noteId: string; + relationName: string; + sourceNoteId: string; } export default function DeleteNotesDialog() { @@ -34,20 +41,51 @@ export default function DeleteNotesDialog() { const [ deleteAllClones, setDeleteAllClones ] = useState(false); const [ eraseNotes, setEraseNotes ] = useState(!!opts.forceDeleteAllClones); const [ brokenRelations, setBrokenRelations ] = useState([]); - const [ noteIdsToBeDeleted, setNoteIdsToBeDeleted ] = useState([]); + const [ noteIdsToBeDeleted, setNoteIdsToBeDeleted ] = useState([]); const [ shown, setShown ] = useState(false); + const [ cloneInfo, setCloneInfo ] = useState({ totalCloneCount: 0 }); const okButtonRef = useRef(null); useTriliumEvent("showDeleteNotesDialog", (opts) => { setOpts(opts); + setDeleteAllClones(false); + setEraseNotes(!!opts.forceDeleteAllClones); setShown(true); - }) + }); + + // Calculate clone information when branches change + useEffect(() => { + const { branchIdsToDelete } = opts; + if (!branchIdsToDelete || branchIdsToDelete.length === 0) { + setCloneInfo({ totalCloneCount: 0 }); + return; + } + + async function calculateCloneInfo() { + const branches = froca.getBranches(branchIdsToDelete!, true); + const uniqueNoteIds = [...new Set(branches.map(b => b.noteId))]; + const notes = await froca.getNotes(uniqueNoteIds); + + let totalCloneCount = 0; + + for (const note of notes) { + const parentBranches = note.getParentBranches(); + // Clones are additional parent branches beyond the one being deleted + const otherBranches = parentBranches.filter(b => !branchIdsToDelete!.includes(b.branchId)); + totalCloneCount += otherBranches.length; + } + + setCloneInfo({ totalCloneCount }); + } + + calculateCloneInfo(); + }, [opts.branchIdsToDelete]); useEffect(() => { const { branchIdsToDelete, forceDeleteAllClones } = opts; if (!branchIdsToDelete || branchIdsToDelete.length === 0) { return; - } + } server.post("delete-notes-preview", { branchIdsToDelete, @@ -63,16 +101,16 @@ export default function DeleteNotesDialog() { className="delete-notes-dialog" size="xl" scrollable - title={t("delete_notes.delete_notes_preview")} + title={t("delete_notes.title")} onShown={() => okButtonRef.current?.focus()} onHidden={() => { - opts.callback?.({ proceed: false }) + opts.callback?.({ proceed: false }); setShown(false); }} footer={<>
); } +function OpenAllButton({ note, isOpening, setIsOpening }: { + note: FNote; + isOpening: boolean; + setIsOpening: (value: boolean) => void; +}) { + const noteIds = note.getChildNoteIds(); + const count = noteIds.length; + + const handleOpenAll = async () => { + if (count === 0) return; + + if (count > MAX_OPEN_TABS) { + await dialogService.info(t("book_properties.open_all_too_many", { count, max: MAX_OPEN_TABS })); + return; + } + + if (count > 10) { + const confirmed = await dialogService.confirm(t("book_properties.open_all_confirm", { count })); + if (!confirmed) return; + } + + setIsOpening(true); + try { + for (let i = 0; i < noteIds.length; i++) { + const noteId = noteIds[i]; + const isLast = i === noteIds.length - 1; + await appContext.tabManager.openTabWithNoteWithHoisting(noteId, { + activate: isLast + }); + } + } finally { + setIsOpening(false); + } + }; + + return ( + + ); +} + function ViewTypeSwitcher({ viewType, setViewType }: { viewType: ViewTypeOptions, setViewType: (newValue: ViewTypeOptions) => void }) { // Keyboard shortcut const dropdownContainerRef = useRef(null); diff --git a/apps/client/src/widgets/note_icon.tsx b/apps/client/src/widgets/note_icon.tsx index 31ca7e65b4..c6ed7e618b 100644 --- a/apps/client/src/widgets/note_icon.tsx +++ b/apps/client/src/widgets/note_icon.tsx @@ -42,8 +42,11 @@ export default function NoteIcon() { setIcon(note?.getIcon()); }, [ note, iconClass, workspaceIconClass ]); + const isDisabled = viewScope?.viewMode !== "default" + || note?.isMetadataReadOnly; + if (isMobile()) { - return ; + return ; } return ( @@ -55,16 +58,17 @@ export default function NoteIcon() { dropdownOptions={{ autoClose: "outside" }} buttonClassName={`note-icon tn-focusable-button ${icon ?? "bx bx-empty"}`} hideToggleArrow - disabled={viewScope?.viewMode !== "default"} + disabled={isDisabled} > { note && dropdownRef?.current?.hide()} columnCount={12} /> } ); } -function MobileNoteIconSwitcher({ note, icon }: { +function MobileNoteIconSwitcher({ note, icon, disabled }: { note: FNote | null | undefined; icon: string | null | undefined; + disabled?: boolean; }) { const [ modalShown, setModalShown ] = useState(false); const { windowWidth } = useWindowSize(); @@ -76,6 +80,7 @@ function MobileNoteIconSwitcher({ note, icon }: { icon={icon ?? "bx bx-empty"} text={t("note_icon.change_note_icon")} onClick={() => setModalShown(true)} + disabled={disabled} /> {createPortal(( diff --git a/apps/client/src/widgets/note_map/NoteMap.css b/apps/client/src/widgets/note_map/NoteMap.css index fa49bb39c6..3188f09439 100644 --- a/apps/client/src/widgets/note_map/NoteMap.css +++ b/apps/client/src/widgets/note_map/NoteMap.css @@ -1,5 +1,5 @@ .note-detail-note-map { - height: 100%; + height: 100%; overflow: hidden; } @@ -54,4 +54,4 @@ width: 10px; } -/* End of styling the slider */ \ No newline at end of file +/* End of styling the slider */ diff --git a/apps/client/src/widgets/note_map/NoteMap.tsx b/apps/client/src/widgets/note_map/NoteMap.tsx index 12e15202d2..a165d467bb 100644 --- a/apps/client/src/widgets/note_map/NoteMap.tsx +++ b/apps/client/src/widgets/note_map/NoteMap.tsx @@ -1,18 +1,25 @@ -import { useEffect, useMemo, useRef, useState } from "preact/hooks"; import "./NoteMap.css"; -import { getThemeStyle, MapType, NoteMapWidgetMode, rgb2hex } from "./utils"; -import { RefObject } from "preact"; -import FNote from "../../entities/fnote"; -import { useElementSize, useNoteLabel } from "../react/hooks"; + import ForceGraph from "force-graph"; +import { RefObject } from "preact"; +import { useEffect, useMemo, useRef, useState } from "preact/hooks"; + +import appContext from "../../components/app_context"; +import FNote from "../../entities/fnote"; +import link_context_menu from "../../menus/link_context_menu"; +import hoisted_note from "../../services/hoisted_note"; +import { t } from "../../services/i18n"; +import { getEffectiveThemeStyle } from "../../services/theme"; +import ActionButton from "../react/ActionButton"; +import { useElementSize, useNoteLabel } from "../react/hooks"; +import NoItems from "../react/NoItems"; +import Slider from "../react/Slider"; import { loadNotesAndRelations, NoteMapLinkObject, NoteMapNodeObject, NotesAndRelationsData } from "./data"; import { CssData, setupRendering } from "./rendering"; -import ActionButton from "../react/ActionButton"; -import { t } from "../../services/i18n"; -import link_context_menu from "../../menus/link_context_menu"; -import appContext from "../../components/app_context"; -import Slider from "../react/Slider"; -import hoisted_note from "../../services/hoisted_note"; +import { MapType, NoteMapWidgetMode, rgb2hex } from "./utils"; + +/** Maximum number of notes to render in the note map before showing a warning. */ +const MAX_NOTES_THRESHOLD = 1_000; interface NoteMapProps { note: FNote; @@ -31,6 +38,7 @@ export default function NoteMap({ note, widgetMode, parentRef }: NoteMapProps) { const containerSize = useElementSize(parentRef); const [ fixNodes, setFixNodes ] = useState(false); const [ linkDistance, setLinkDistance ] = useState(40); + const [ tooManyNotes, setTooManyNotes ] = useState(null); const notesAndRelationsRef = useRef(); const mapRootId = useMemo(() => { @@ -40,9 +48,9 @@ export default function NoteMap({ note, widgetMode, parentRef }: NoteMapProps) { return hoisted_note.getHoistedNoteId(); } else if (mapRootIdLabel) { return mapRootIdLabel; - } else { - return appContext.tabManager.getActiveContext()?.parentNoteId ?? null; } + return appContext.tabManager.getActiveContext()?.parentNoteId ?? null; + }, [ note ]); // Build the note graph instance. @@ -58,6 +66,14 @@ export default function NoteMap({ note, widgetMode, parentRef }: NoteMapProps) { const includeRelations = labelValues("mapIncludeRelation"); loadNotesAndRelations(mapRootId, excludeRelations, includeRelations, mapType).then((notesAndRelations) => { if (!containerRef.current || !styleResolverRef.current) return; + + // Guard against rendering too many notes which would freeze the browser. + if (notesAndRelations.nodes.length > MAX_NOTES_THRESHOLD) { + setTooManyNotes(notesAndRelations.nodes.length); + return; + } + setTooManyNotes(null); + const cssData = getCssData(containerRef.current, styleResolverRef.current); // Configure rendering properties. @@ -67,7 +83,7 @@ export default function NoteMap({ note, widgetMode, parentRef }: NoteMapProps) { noteIdToSizeMap: notesAndRelations.noteIdToSizeMap, cssData, notesAndRelations, - themeStyle: getThemeStyle(), + themeStyle: getEffectiveThemeStyle(), widgetMode, mapType }); @@ -113,9 +129,15 @@ export default function NoteMap({ note, widgetMode, parentRef }: NoteMapProps) { node.fx = undefined; node.fy = undefined; } - }) + }); }, [ fixNodes, mapType ]); + if (tooManyNotes) { + return ( + + ); + } + return (
@@ -159,7 +181,7 @@ function MapTypeSwitcher({ icon, text, type, currentMapType, setMapType }: { onClick={() => setMapType(type)} frame /> - ) + ); } function getCssData(container: HTMLElement, styleResolver: HTMLElement): CssData { @@ -170,5 +192,5 @@ function getCssData(container: HTMLElement, styleResolver: HTMLElement): CssData fontFamily: containerStyle.fontFamily, textColor: rgb2hex(containerStyle.color), mutedTextColor: rgb2hex(styleResolverStyle.color) - } + }; } diff --git a/apps/client/src/widgets/note_map/utils.ts b/apps/client/src/widgets/note_map/utils.ts index d551ea235b..923b5cb001 100644 --- a/apps/client/src/widgets/note_map/utils.ts +++ b/apps/client/src/widgets/note_map/utils.ts @@ -27,7 +27,3 @@ export function generateColorFromString(str: string, themeStyle: "light" | "dark return color; } -export function getThemeStyle() { - const documentStyle = window.getComputedStyle(document.documentElement); - return documentStyle.getPropertyValue("--theme-style")?.trim() as "light" | "dark"; -} diff --git a/apps/client/src/widgets/note_title.tsx b/apps/client/src/widgets/note_title.tsx index f886d9f7db..34b27c9298 100644 --- a/apps/client/src/widgets/note_title.tsx +++ b/apps/client/src/widgets/note_title.tsx @@ -1,15 +1,16 @@ -import { useEffect, useRef, useState } from "preact/hooks"; -import { t } from "../services/i18n"; -import FormTextBox from "./react/FormTextBox"; -import { useNoteContext, useNoteProperty, useSpacedUpdate, useTriliumEvent, useTriliumEvents } from "./react/hooks"; -import protected_session_holder from "../services/protected_session_holder"; -import server from "../services/server"; import "./note_title.css"; -import { isLaunchBarConfig } from "../services/utils"; + +import clsx from "clsx"; +import { useEffect, useRef, useState } from "preact/hooks"; + import appContext from "../components/app_context"; import branches from "../services/branches"; +import { t } from "../services/i18n"; +import protected_session_holder from "../services/protected_session_holder"; +import server from "../services/server"; import { isIMEComposing } from "../services/shortcuts"; -import clsx from "clsx"; +import FormTextBox from "./react/FormTextBox"; +import { useNoteContext, useNoteProperty, useSpacedUpdate, useTriliumEvent, useTriliumEvents } from "./react/hooks"; export default function NoteTitleWidget(props: {className?: string}) { const { note, noteId, componentId, viewScope, noteContext, parentComponent } = useNoteContext(); @@ -25,8 +26,7 @@ export default function NoteTitleWidget(props: {className?: string}) { const isReadOnly = note === null || note === undefined || (note.isProtected && !protected_session_holder.isProtectedSessionAvailable()) - || isLaunchBarConfig(note.noteId) - || note.noteId.startsWith("_help_") + || note.isMetadataReadOnly || viewScope?.viewMode !== "default"; setReadOnly(isReadOnly); }, [ note, note?.noteId, note?.isProtected, viewScope?.viewMode ]); @@ -58,11 +58,29 @@ export default function NoteTitleWidget(props: {className?: string}) { // Manage focus. const textBoxRef = useRef(null); const isNewNote = useRef(); + const pendingSelect = useRef(false); + + // Re-apply selection when title changes if we have a pending select. + // This handles the case where the server sends back entity changes after we've + // already called select(), which causes the controlled input to re-render and lose selection. + useEffect(() => { + if (pendingSelect.current && textBoxRef.current && document.activeElement === textBoxRef.current) { + textBoxRef.current.select(); + pendingSelect.current = false; + } + }, [title]); + useTriliumEvents([ "focusOnTitle", "focusAndSelectTitle" ], (e, eventName) => { if (noteContext?.isActive() && textBoxRef.current) { + // In the new layout, there are two NoteTitleWidget instances. Only handle if visible. + if (!textBoxRef.current.checkVisibility({ checkOpacity: true })) { + return; + } + textBoxRef.current.focus(); if (eventName === "focusAndSelectTitle") { textBoxRef.current.select(); + pendingSelect.current = true; } isNewNote.current = ("isNewNote" in e ? e.isNewNote : false); } @@ -83,6 +101,9 @@ export default function NoteTitleWidget(props: {className?: string}) { spacedUpdate.scheduleUpdate(); }} onKeyDown={(e) => { + // User started typing, stop re-applying selection + pendingSelect.current = false; + // Skip processing if IME is composing to prevent interference // with text input in CJK languages if (isIMEComposing(e)) { @@ -101,6 +122,7 @@ export default function NoteTitleWidget(props: {className?: string}) { } }} onBlur={() => { + pendingSelect.current = false; spacedUpdate.updateNowIfNecessary(); isNewNote.current = false; }} diff --git a/apps/client/src/widgets/quick_search.ts b/apps/client/src/widgets/quick_search.ts index cc326df983..df0edb2a90 100644 --- a/apps/client/src/widgets/quick_search.ts +++ b/apps/client/src/widgets/quick_search.ts @@ -1,13 +1,14 @@ -import BasicWidget from "./basic_widget.js"; -import server from "../services/server.js"; -import linkService from "../services/link.js"; -import froca from "../services/froca.js"; -import utils, { handleRightToLeftPlacement } from "../services/utils.js"; -import appContext from "../components/app_context.js"; -import shortcutService, { isIMEComposing } from "../services/shortcuts.js"; -import { t } from "../services/i18n.js"; import { Dropdown, Tooltip } from "bootstrap"; +import appContext from "../components/app_context.js"; +import froca from "../services/froca.js"; +import { t } from "../services/i18n.js"; +import linkService from "../services/link.js"; +import server from "../services/server.js"; +import shortcutService, { isIMEComposing } from "../services/shortcuts.js"; +import utils, { handleRightToLeftPlacement } from "../services/utils.js"; +import BasicWidget from "./basic_widget.js"; + const TPL = /*html*/`