diff --git a/.nvmrc b/.nvmrc index cf2efde811..f94d3c2ea9 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -24.13.0 \ No newline at end of file +24.13.1 \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 57d22dcb8e..974a4ff64e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -42,5 +42,8 @@ }, "eslint.rules.customizations": [ { "rule": "*", "severity": "warn" } + ], + "cSpell.words": [ + "Trilium" ] -} \ No newline at end of file +} diff --git a/apps/build-docs/package.json b/apps/build-docs/package.json index ac5be7e9be..934f610b9e 100644 --- a/apps/build-docs/package.json +++ b/apps/build-docs/package.json @@ -1,22 +1,28 @@ { "name": "build-docs", "version": "1.0.0", - "description": "", + "description": "Build documentation from Trilium notes", "main": "src/main.ts", + "bin": { + "trilium-build-docs": "dist/cli.js" + }, "scripts": { - "start": "tsx ." + "start": "tsx .", + "cli": "tsx src/cli.ts", + "build": "tsx scripts/build.ts" }, "keywords": [], "author": "Elian Doran ", "license": "AGPL-3.0-only", - "packageManager": "pnpm@10.28.2", + "packageManager": "pnpm@10.30.1", "devDependencies": { - "@redocly/cli": "2.15.0", + "@redocly/cli": "2.19.1", "archiver": "7.0.1", "fs-extra": "11.3.3", + "js-yaml": "4.1.1", "react": "19.2.4", "react-dom": "19.2.4", - "typedoc": "0.28.16", + "typedoc": "0.28.17", "typedoc-plugin-missing-exports": "4.1.2" } } diff --git a/apps/build-docs/scripts/build.ts b/apps/build-docs/scripts/build.ts new file mode 100644 index 0000000000..79fa01f3f6 --- /dev/null +++ b/apps/build-docs/scripts/build.ts @@ -0,0 +1,23 @@ +import BuildHelper from "../../../scripts/build-utils"; + +const build = new BuildHelper("apps/build-docs"); + +async function main() { + // Build the CLI and other TypeScript files + await build.buildBackend([ + "src/cli.ts", + "src/main.ts", + "src/build-docs.ts", + "src/swagger.ts", + "src/script-api.ts", + "src/context.ts" + ]); + + // Copy HTML template + build.copy("src/index.html", "index.html"); + + // Copy node modules dependencies if needed + build.copyNodeModules([ "better-sqlite3", "bindings", "file-uri-to-path" ]); +} + +main(); diff --git a/apps/build-docs/src/backend_script_entrypoint.ts b/apps/build-docs/src/backend_script_entrypoint.ts index bc9087c0c1..0447900b6b 100644 --- a/apps/build-docs/src/backend_script_entrypoint.ts +++ b/apps/build-docs/src/backend_script_entrypoint.ts @@ -13,8 +13,12 @@ * Make sure to keep in line with backend's `script_context.ts`. */ -export type { default as AbstractBeccaEntity } from "../../server/src/becca/entities/abstract_becca_entity.js"; -export type { default as BAttachment } from "../../server/src/becca/entities/battachment.js"; +export type { + default as AbstractBeccaEntity +} from "../../server/src/becca/entities/abstract_becca_entity.js"; +export type { + default as BAttachment +} from "../../server/src/becca/entities/battachment.js"; export type { default as BAttribute } from "../../server/src/becca/entities/battribute.js"; export type { default as BBranch } from "../../server/src/becca/entities/bbranch.js"; export type { default as BEtapiToken } from "../../server/src/becca/entities/betapi_token.js"; @@ -31,6 +35,7 @@ export type { Api }; const fakeNote = new BNote(); /** - * The `api` global variable allows access to the backend script API, which is documented in {@link Api}. + * The `api` global variable allows access to the backend script API, + * which is documented in {@link Api}. */ export const api: Api = new BackendScriptApi(fakeNote, {}); diff --git a/apps/build-docs/src/build-docs.ts b/apps/build-docs/src/build-docs.ts index 5d1a0cdd6f..357ecb1d41 100644 --- a/apps/build-docs/src/build-docs.ts +++ b/apps/build-docs/src/build-docs.ts @@ -1,19 +1,90 @@ process.env.TRILIUM_INTEGRATION_TEST = "memory-no-store"; -process.env.TRILIUM_RESOURCE_DIR = "../server/src"; +// Only set TRILIUM_RESOURCE_DIR if not already set (e.g., by Nix wrapper) +if (!process.env.TRILIUM_RESOURCE_DIR) { + process.env.TRILIUM_RESOURCE_DIR = "../server/src"; +} process.env.NODE_ENV = "development"; import cls from "@triliumnext/server/src/services/cls.js"; -import { dirname, join, resolve } from "path"; +import archiver from "archiver"; +import { execSync } from "child_process"; +import { WriteStream } from "fs"; import * as fs from "fs/promises"; import * as fsExtra from "fs-extra"; -import archiver from "archiver"; -import { WriteStream } from "fs"; -import { execSync } from "child_process"; +import yaml from "js-yaml"; +import { dirname, join, resolve } from "path"; + import BuildContext from "./context.js"; +interface NoteMapping { + rootNoteId: string; + path: string; + format: "markdown" | "html" | "share"; + ignoredFiles?: string[]; + exportOnly?: boolean; +} + +interface Config { + baseUrl: string; + noteMappings: NoteMapping[]; +} + const DOCS_ROOT = "../../../docs"; const OUTPUT_DIR = "../../site"; +// Load configuration from edit-docs-config.yaml +async function loadConfig(configPath?: string): Promise { + const pathsToTry = configPath + ? [resolve(configPath)] + : [ + join(process.cwd(), "edit-docs-config.yaml"), + join(__dirname, "../../../edit-docs-config.yaml") + ]; + + for (const path of pathsToTry) { + try { + const configContent = await fs.readFile(path, "utf-8"); + const config = yaml.load(configContent) as Config; + + // Resolve all paths relative to the config file's directory + const CONFIG_DIR = dirname(path); + config.noteMappings = config.noteMappings.map((mapping) => ({ + ...mapping, + path: resolve(CONFIG_DIR, mapping.path) + })); + + return config; + } catch (error) { + if (error.code !== "ENOENT") { + throw error; // rethrow unexpected errors + } + } + } + + return null; // No config file found +} + +async function exportDocs( + noteId: string, + format: "markdown" | "html" | "share", + outputPath: string, + ignoredFiles?: string[] +) { + const zipFilePath = `output-${noteId}.zip`; + try { + const { exportToZipFile } = (await import("@triliumnext/server/src/services/export/zip.js")) + .default; + await exportToZipFile(noteId, format, zipFilePath, {}); + + const ignoredSet = ignoredFiles ? new Set(ignoredFiles) : undefined; + await extractZip(zipFilePath, outputPath, ignoredSet); + } finally { + if (await fsExtra.exists(zipFilePath)) { + await fsExtra.rm(zipFilePath); + } + } +} + async function importAndExportDocs(sourcePath: string, outputSubDir: string) { const note = await importData(sourcePath); @@ -21,15 +92,18 @@ async function importAndExportDocs(sourcePath: string, outputSubDir: string) { const zipName = outputSubDir || "user-guide"; const zipFilePath = `output-${zipName}.zip`; try { - const { exportToZip } = (await import("@triliumnext/server/src/services/export/zip.js")).default; + const { exportToZip } = (await import("@triliumnext/server/src/services/export/zip.js")) + .default; const branch = note.getParentBranches()[0]; - const taskContext = new (await import("@triliumnext/server/src/services/task_context.js")).default( - "no-progress-reporting", - "export", - null - ); + const taskContext = new (await import("@triliumnext/server/src/services/task_context.js")) + .default( + "no-progress-reporting", + "export", + null + ); const fileOutputStream = fsExtra.createWriteStream(zipFilePath); await exportToZip(taskContext, branch, "share", fileOutputStream); + const { waitForStreamToFinish } = await import("@triliumnext/server/src/services/utils.js"); await waitForStreamToFinish(fileOutputStream); // Output to root directory if outputSubDir is empty, otherwise to subdirectory @@ -42,7 +116,7 @@ async function importAndExportDocs(sourcePath: string, outputSubDir: string) { } } -async function buildDocsInner() { +async function buildDocsInner(config?: Config) { const i18n = await import("@triliumnext/server/src/services/i18n.js"); await i18n.initializeTranslations(); @@ -53,18 +127,49 @@ async function buildDocsInner() { const beccaLoader = await import("../../server/src/becca/becca_loader.js"); await beccaLoader.beccaLoaded; - // Build User Guide - console.log("Building User Guide..."); - await importAndExportDocs(join(__dirname, DOCS_ROOT, "User Guide"), "user-guide"); + if (config) { + // Config-based build (reads from edit-docs-config.yaml) + console.log("Building documentation from config file..."); - // Build Developer Guide - console.log("Building Developer Guide..."); - await importAndExportDocs(join(__dirname, DOCS_ROOT, "Developer Guide"), "developer-guide"); + // Import all non-export-only mappings + for (const mapping of config.noteMappings) { + if (!mapping.exportOnly) { + console.log(`Importing from ${mapping.path}...`); + await importData(mapping.path); + } + } - // Copy favicon. - await fs.copyFile("../../apps/website/src/assets/favicon.ico", join(OUTPUT_DIR, "favicon.ico")); - await fs.copyFile("../../apps/website/src/assets/favicon.ico", join(OUTPUT_DIR, "user-guide", "favicon.ico")); - await fs.copyFile("../../apps/website/src/assets/favicon.ico", join(OUTPUT_DIR, "developer-guide", "favicon.ico")); + // Export all mappings + for (const mapping of config.noteMappings) { + if (mapping.exportOnly) { + console.log(`Exporting ${mapping.format} to ${mapping.path}...`); + await exportDocs( + mapping.rootNoteId, + mapping.format, + mapping.path, + mapping.ignoredFiles + ); + } + } + } else { + // Legacy hardcoded build (for backward compatibility) + console.log("Building User Guide..."); + await importAndExportDocs(join(__dirname, DOCS_ROOT, "User Guide"), "user-guide"); + + console.log("Building Developer Guide..."); + await importAndExportDocs( + join(__dirname, DOCS_ROOT, "Developer Guide"), + "developer-guide" + ); + + // Copy favicon. + await fs.copyFile("../../apps/website/src/assets/favicon.ico", + join(OUTPUT_DIR, "favicon.ico")); + await fs.copyFile("../../apps/website/src/assets/favicon.ico", + join(OUTPUT_DIR, "user-guide", "favicon.ico")); + await fs.copyFile("../../apps/website/src/assets/favicon.ico", + join(OUTPUT_DIR, "developer-guide", "favicon.ico")); + } console.log("Documentation built successfully!"); } @@ -91,12 +196,13 @@ async function createImportZip(path: string) { zlib: { level: 0 } }); - console.log("Archive path is ", resolve(path)) + console.log("Archive path is ", resolve(path)); archive.directory(path, "/"); const outputStream = fsExtra.createWriteStream(inputFile); archive.pipe(outputStream); archive.finalize(); + const { waitForStreamToFinish } = await import("@triliumnext/server/src/services/utils.js"); await waitForStreamToFinish(outputStream); try { @@ -106,15 +212,15 @@ async function createImportZip(path: string) { } } -function waitForStreamToFinish(stream: WriteStream) { - return new Promise((res, rej) => { - stream.on("finish", () => res()); - stream.on("error", (err) => rej(err)); - }); -} -export async function extractZip(zipFilePath: string, outputPath: string, ignoredFiles?: Set) { - const { readZipFile, readContent } = (await import("@triliumnext/server/src/services/import/zip.js")); +export async function extractZip( + zipFilePath: string, + outputPath: string, + ignoredFiles?: Set +) { + const { readZipFile, readContent } = (await import( + "@triliumnext/server/src/services/import/zip.js" + )); await readZipFile(await fs.readFile(zipFilePath), async (zip, entry) => { // We ignore directories since they can appear out of order anyway. if (!entry.fileName.endsWith("/") && !ignoredFiles?.has(entry.fileName)) { @@ -129,6 +235,27 @@ export async function extractZip(zipFilePath: string, outputPath: string, ignore }); } +export async function buildDocsFromConfig(configPath?: string, gitRootDir?: string) { + const config = await loadConfig(configPath); + + if (gitRootDir) { + // Build the share theme if we have a gitRootDir (for Trilium project) + execSync(`pnpm run --filter share-theme build`, { + stdio: "inherit", + cwd: gitRootDir + }); + } + + // Trigger the actual build. + await new Promise((res, rej) => { + cls.init(() => { + buildDocsInner(config ?? undefined) + .catch(rej) + .then(res); + }); + }); +} + export default async function buildDocs({ gitRootDir }: BuildContext) { // Build the share theme. execSync(`pnpm run --filter share-theme build`, { diff --git a/apps/build-docs/src/cli.ts b/apps/build-docs/src/cli.ts new file mode 100644 index 0000000000..8aee089701 --- /dev/null +++ b/apps/build-docs/src/cli.ts @@ -0,0 +1,89 @@ +#!/usr/bin/env node + +import packageJson from "../package.json" with { type: "json" }; +import { buildDocsFromConfig } from "./build-docs.js"; + +// Parse command-line arguments +function parseArgs() { + const args = process.argv.slice(2); + let configPath: string | undefined; + let showHelp = false; + let showVersion = false; + + for (let i = 0; i < args.length; i++) { + if (args[i] === "--config" || args[i] === "-c") { + configPath = args[i + 1]; + if (!configPath) { + console.error("Error: --config/-c requires a path argument"); + process.exit(1); + } + i++; // Skip the next argument as it's the value + } else if (args[i] === "--help" || args[i] === "-h") { + showHelp = true; + } else if (args[i] === "--version" || args[i] === "-v") { + showVersion = true; + } + } + + return { configPath, showHelp, showVersion }; +} + +function getVersion(): string { + return packageJson.version; +} + +function printHelp() { + const version = getVersion(); + console.log(` +Usage: trilium-build-docs [options] + +Options: + -c, --config Path to the configuration file + (default: edit-docs-config.yaml in current directory) + -h, --help Display this help message + -v, --version Display version information + +Description: + Builds documentation from Trilium note structure and exports to various formats. + Configuration file should be in YAML format with the following structure: + + baseUrl: "https://example.com" + noteMappings: + - rootNoteId: "noteId123" + path: "docs" + format: "markdown" + - rootNoteId: "noteId456" + path: "public/docs" + format: "share" + exportOnly: true + +Version: ${version} +`); +} + +function printVersion() { + const version = getVersion(); + console.log(version); +} + +async function main() { + const { configPath, showHelp, showVersion } = parseArgs(); + + if (showHelp) { + printHelp(); + process.exit(0); + } else if (showVersion) { + printVersion(); + process.exit(0); + } + + try { + await buildDocsFromConfig(configPath); + process.exit(0); + } catch (error) { + console.error("Error building documentation:", error); + process.exit(1); + } +} + +main(); diff --git a/apps/build-docs/src/frontend_script_entrypoint.ts b/apps/build-docs/src/frontend_script_entrypoint.ts index 768774eca6..7aba11b2a4 100644 --- a/apps/build-docs/src/frontend_script_entrypoint.ts +++ b/apps/build-docs/src/frontend_script_entrypoint.ts @@ -13,16 +13,19 @@ * Make sure to keep in line with frontend's `script_context.ts`. */ -export type { default as BasicWidget } from "../../client/src/widgets/basic_widget.js"; export type { default as FAttachment } from "../../client/src/entities/fattachment.js"; export type { default as FAttribute } from "../../client/src/entities/fattribute.js"; export type { default as FBranch } from "../../client/src/entities/fbranch.js"; export type { default as FNote } from "../../client/src/entities/fnote.js"; export type { Api } from "../../client/src/services/frontend_script_api.js"; -export type { default as NoteContextAwareWidget } from "../../client/src/widgets/note_context_aware_widget.js"; +export type { default as BasicWidget } from "../../client/src/widgets/basic_widget.js"; +export type { + default as NoteContextAwareWidget +} from "../../client/src/widgets/note_context_aware_widget.js"; export type { default as RightPanelWidget } from "../../client/src/widgets/right_panel_widget.js"; import FrontendScriptApi, { type Api } from "../../client/src/services/frontend_script_api.js"; -//@ts-expect-error + +// @ts-expect-error - FrontendScriptApi is not directly exportable as Api without this simulation. export const api: Api = new FrontendScriptApi(); diff --git a/apps/build-docs/src/main.ts b/apps/build-docs/src/main.ts index d94ada167b..cca17125d8 100644 --- a/apps/build-docs/src/main.ts +++ b/apps/build-docs/src/main.ts @@ -1,9 +1,10 @@ -import { join } from "path"; -import BuildContext from "./context"; -import buildSwagger from "./swagger"; import { cpSync, existsSync, mkdirSync, rmSync } from "fs"; +import { join } from "path"; + import buildDocs from "./build-docs"; +import BuildContext from "./context"; import buildScriptApi from "./script-api"; +import buildSwagger from "./swagger"; const context: BuildContext = { gitRootDir: join(__dirname, "../../../"), diff --git a/apps/build-docs/src/script-api.ts b/apps/build-docs/src/script-api.ts index 8473ae3a02..2c62477474 100644 --- a/apps/build-docs/src/script-api.ts +++ b/apps/build-docs/src/script-api.ts @@ -1,7 +1,8 @@ import { execSync } from "child_process"; -import BuildContext from "./context"; import { join } from "path"; +import BuildContext from "./context"; + export default function buildScriptApi({ baseDir, gitRootDir }: BuildContext) { // Generate types execSync(`pnpm typecheck`, { stdio: "inherit", cwd: gitRootDir }); diff --git a/apps/build-docs/src/swagger.ts b/apps/build-docs/src/swagger.ts index b3677aeebe..2af458ec47 100644 --- a/apps/build-docs/src/swagger.ts +++ b/apps/build-docs/src/swagger.ts @@ -1,7 +1,8 @@ -import BuildContext from "./context"; -import { join } from "path"; import { execSync } from "child_process"; import { mkdirSync } from "fs"; +import { join } from "path"; + +import BuildContext from "./context"; interface BuildInfo { specPath: string; @@ -27,6 +28,9 @@ export default function buildSwagger({ baseDir, gitRootDir }: BuildContext) { const absSpecPath = join(gitRootDir, specPath); const targetDir = join(baseDir, outDir); mkdirSync(targetDir, { recursive: true }); - execSync(`pnpm redocly build-docs ${absSpecPath} -o ${targetDir}/index.html`, { stdio: "inherit" }); + execSync( + `pnpm redocly build-docs ${absSpecPath} -o ${targetDir}/index.html`, + { stdio: "inherit" } + ); } } diff --git a/apps/build-docs/tsconfig.json b/apps/build-docs/tsconfig.json index 858921cfb6..99c9b71b37 100644 --- a/apps/build-docs/tsconfig.json +++ b/apps/build-docs/tsconfig.json @@ -1,6 +1,8 @@ { "extends": "../../tsconfig.base.json", - "include": [], + "include": [ + "scripts/**/*.ts" + ], "references": [ { "path": "../server" diff --git a/apps/build-docs/typedoc.backend.json b/apps/build-docs/typedoc.backend.json index 1781774c6f..a7f91c42e4 100644 --- a/apps/build-docs/typedoc.backend.json +++ b/apps/build-docs/typedoc.backend.json @@ -4,6 +4,7 @@ "entryPoints": [ "src/backend_script_entrypoint.ts" ], + "tsconfig": "tsconfig.app.json", "plugin": [ "typedoc-plugin-missing-exports" ] diff --git a/apps/build-docs/typedoc.frontend.json b/apps/build-docs/typedoc.frontend.json index f07d20dc71..c462004712 100644 --- a/apps/build-docs/typedoc.frontend.json +++ b/apps/build-docs/typedoc.frontend.json @@ -4,6 +4,7 @@ "entryPoints": [ "src/frontend_script_entrypoint.ts" ], + "tsconfig": "tsconfig.app.json", "plugin": [ "typedoc-plugin-missing-exports" ] diff --git a/apps/client/package.json b/apps/client/package.json index e0840ccd04..eb5f39aca1 100644 --- a/apps/client/package.json +++ b/apps/client/package.json @@ -27,7 +27,7 @@ "@mermaid-js/layout-elk": "0.2.0", "@mind-elixir/node-menu": "5.0.1", "@popperjs/core": "2.11.8", - "@preact/signals": "2.6.2", + "@preact/signals": "2.8.1", "@triliumnext/ckeditor5": "workspace:*", "@triliumnext/codemirror": "workspace:*", "@triliumnext/commons": "workspace:*", @@ -42,9 +42,9 @@ "color": "5.0.3", "debounce": "3.0.0", "draggabilly": "3.0.0", - "force-graph": "1.51.0", - "globals": "17.2.0", - "i18next": "25.8.0", + "force-graph": "1.51.1", + "globals": "17.3.0", + "i18next": "25.8.13", "i18next-http-backend": "3.0.2", "jquery": "4.0.0", "jquery.fancytree": "2.38.5", @@ -54,14 +54,14 @@ "leaflet": "1.9.4", "leaflet-gpx": "2.2.0", "mark.js": "8.11.1", - "marked": "17.0.1", - "mermaid": "11.12.2", - "mind-elixir": "5.6.1", + "marked": "17.0.3", + "mermaid": "11.12.3", + "mind-elixir": "5.8.3", "normalize.css": "8.0.1", "panzoom": "9.4.3", - "preact": "10.28.3", + "preact": "10.28.4", "react-i18next": "16.5.4", - "react-window": "2.2.6", + "react-window": "2.2.7", "reveal.js": "5.2.1", "svg-pan-zoom": "3.6.2", "tabulator-tables": "6.3.1", @@ -69,7 +69,7 @@ }, "devDependencies": { "@ckeditor/ckeditor5-inspector": "5.0.0", - "@prefresh/vite": "2.4.11", + "@prefresh/vite": "2.4.12", "@types/bootstrap": "5.2.10", "@types/jquery": "3.5.33", "@types/leaflet": "1.9.21", @@ -78,7 +78,7 @@ "@types/reveal.js": "5.2.2", "@types/tabulator-tables": "6.3.1", "copy-webpack-plugin": "13.0.1", - "happy-dom": "20.4.0", + "happy-dom": "20.7.0", "lightningcss": "1.31.1", "script-loader": "0.7.2", "vite-plugin-static-copy": "3.2.0" diff --git a/apps/client/src/desktop.ts b/apps/client/src/desktop.ts index bba3b6b90b..6f22d3fc7b 100644 --- a/apps/client/src/desktop.ts +++ b/apps/client/src/desktop.ts @@ -46,10 +46,6 @@ if (utils.isElectron()) { electronContextMenu.setupContextMenu(); } -if (utils.isPWA()) { - initPWATopbarColor(); -} - function initOnElectron() { const electron: typeof Electron = utils.dynamicRequire("electron"); electron.ipcRenderer.on("globalShortcut", async (event, actionName) => appContext.triggerCommand(actionName)); @@ -134,20 +130,3 @@ function initDarkOrLightMode(style: CSSStyleDeclaration) { const { nativeTheme } = utils.dynamicRequire("@electron/remote") as typeof ElectronRemote; nativeTheme.themeSource = themeSource; } - -function initPWATopbarColor() { - const tracker = $("#background-color-tracker"); - - if (tracker.length) { - const applyThemeColor = () => { - let meta = $("meta[name='theme-color']"); - if (!meta.length) { - meta = $(``).appendTo($("head")); - } - meta.attr("content", tracker.css("color")); - }; - - tracker.on("transitionend", applyThemeColor); - applyThemeColor(); - } -} diff --git a/apps/client/src/entities/fnote.ts b/apps/client/src/entities/fnote.ts index f161d7adb1..2b515f2412 100644 --- a/apps/client/src/entities/fnote.ts +++ b/apps/client/src/entities/fnote.ts @@ -700,6 +700,15 @@ export default class FNote { return this.hasAttribute(LABEL, name); } + /** + * Returns `true` if the note has a label with the given name (same as {@link hasOwnedLabel}), or it has a label with the `disabled:` prefix (for example due to a safe import). + * @param name the name of the label to look for. + * @returns `true` if the label exists, or its version with the `disabled:` prefix. + */ + hasLabelOrDisabled(name: string) { + return this.hasLabel(name) || this.hasLabel(`disabled:${name}`); + } + /** * @param name - label name * @returns true if label exists (including inherited) and does not have "false" value. diff --git a/apps/client/src/layouts/mobile_layout.css b/apps/client/src/layouts/mobile_layout.css new file mode 100644 index 0000000000..396fa4a467 --- /dev/null +++ b/apps/client/src/layouts/mobile_layout.css @@ -0,0 +1,76 @@ +#background-color-tracker { + color: var(--main-background-color) !important; +} + +span.keyboard-shortcut, +kbd { + display: none; +} + +.dropdown-menu { + font-size: larger; +} + +.action-button { + background: none; + border: none; + cursor: pointer; + font-size: 1.25em; + padding-inline-start: 0.5em; + padding-inline-end: 0.5em; + color: var(--main-text-color); +} +.quick-search { + margin: 0; +} +.quick-search .dropdown-menu { + max-width: 350px; +} + +/* #region Tree */ +.tree-wrapper { + max-height: 100%; + margin-top: 0px; + overflow-y: auto; + contain: content; + padding-inline-start: 10px; +} + +.fancytree-title { + margin-inline-start: 0.6em !important; +} + +.fancytree-node { + padding: 5px; +} + +span.fancytree-expander { + width: 24px !important; + margin-inline-end: 5px; +} + +.fancytree-loading span.fancytree-expander { + width: 24px; + height: 32px; +} + +.fancytree-loading span.fancytree-expander:after { + width: 20px; + height: 20px; + margin-top: 4px; + border-width: 2px; + border-style: solid; +} + +.tree-wrapper .collapse-tree-button, +.tree-wrapper .scroll-to-active-note-button, +.tree-wrapper .tree-settings-button { + position: fixed; + margin-inline-end: 16px; + display: none; +} + +.tree-wrapper .unhoist-button { + font-size: 200%; +} +/* #endregion */ diff --git a/apps/client/src/layouts/mobile_layout.tsx b/apps/client/src/layouts/mobile_layout.tsx index dbe88ade84..3fc5422b0a 100644 --- a/apps/client/src/layouts/mobile_layout.tsx +++ b/apps/client/src/layouts/mobile_layout.tsx @@ -1,128 +1,38 @@ +import "./mobile_layout.css"; + import type AppContext from "../components/app_context.js"; import GlobalMenuWidget from "../widgets/buttons/global_menu.js"; import CloseZenModeButton from "../widgets/close_zen_button.js"; import NoteList from "../widgets/collections/NoteList.jsx"; -import ContentHeader from "../widgets/containers/content_header.js"; import FlexContainer from "../widgets/containers/flex_container.js"; import RootContainer from "../widgets/containers/root_container.js"; import ScrollingContainer from "../widgets/containers/scrolling_container.js"; import SplitNoteContainer from "../widgets/containers/split_note_container.js"; -import FloatingButtons from "../widgets/FloatingButtons.jsx"; -import { MOBILE_FLOATING_BUTTONS } from "../widgets/FloatingButtonsDefinitions.jsx"; +import FindWidget from "../widgets/find.js"; import LauncherContainer from "../widgets/launch_bar/LauncherContainer.jsx"; +import InlineTitle from "../widgets/layout/InlineTitle.jsx"; +import NoteBadges from "../widgets/layout/NoteBadges.jsx"; +import NoteTitleActions from "../widgets/layout/NoteTitleActions.jsx"; import MobileDetailMenu from "../widgets/mobile_widgets/mobile_detail_menu.js"; import ScreenContainer from "../widgets/mobile_widgets/screen_container.js"; import SidebarContainer from "../widgets/mobile_widgets/sidebar_container.js"; import ToggleSidebarButton from "../widgets/mobile_widgets/toggle_sidebar_button.jsx"; +import NoteIconWidget from "../widgets/note_icon.jsx"; import NoteTitleWidget from "../widgets/note_title.js"; import NoteTreeWidget from "../widgets/note_tree.js"; import NoteWrapperWidget from "../widgets/note_wrapper.js"; import NoteDetail from "../widgets/NoteDetail.jsx"; -import PromotedAttributes from "../widgets/PromotedAttributes.jsx"; import QuickSearchWidget from "../widgets/quick_search.js"; -import { useNoteContext } from "../widgets/react/hooks.jsx"; -import ReadOnlyNoteInfoBar from "../widgets/ReadOnlyNoteInfoBar.jsx"; -import StandaloneRibbonAdapter from "../widgets/ribbon/components/StandaloneRibbonAdapter.jsx"; -import FilePropertiesTab from "../widgets/ribbon/FilePropertiesTab.jsx"; -import SearchDefinitionTab from "../widgets/ribbon/SearchDefinitionTab.jsx"; +import ScrollPadding from "../widgets/scroll_padding"; import SearchResult from "../widgets/search_result.jsx"; -import SharedInfoWidget from "../widgets/shared_info.js"; -import TabRowWidget from "../widgets/tab_row.js"; import MobileEditorToolbar from "../widgets/type_widgets/text/mobile_editor_toolbar.jsx"; import { applyModals } from "./layout_commons.js"; -const MOBILE_CSS = ` -`; - -const FANCYTREE_CSS = ` -`; - export default class MobileLayout { getRootWidget(appContext: typeof AppContext) { const rootContainer = new RootContainer(true) .setParent(appContext) .class("horizontal-layout") - .cssBlock(MOBILE_CSS) .child(new FlexContainer("column").id("mobile-sidebar-container")) .child( new FlexContainer("row") @@ -136,7 +46,7 @@ export default class MobileLayout { .css("padding-inline-start", "0") .css("padding-inline-end", "0") .css("contain", "content") - .child(new FlexContainer("column").filling().id("mobile-sidebar-wrapper").child(new QuickSearchWidget()).child(new NoteTreeWidget().cssBlock(FANCYTREE_CSS))) + .child(new FlexContainer("column").filling().id("mobile-sidebar-wrapper").child(new QuickSearchWidget()).child(new NoteTreeWidget())) ) .child( new ScreenContainer("detail", "row") @@ -147,30 +57,28 @@ export default class MobileLayout { new NoteWrapperWidget() .child( new FlexContainer("row") + .class("title-row note-split-title") .contentSized() - .css("font-size", "larger") .css("align-items", "center") .child() + .child() .child() + .child() .child() ) - .child() - .child() .child( new ScrollingContainer() .filling() .contentSized() - .child(new ContentHeader() - .child() - .child() - ) + .child() + .child() .child() .child() - .child() .child() - .child() + .child() ) .child() + .child(new FindWidget()) ) ) ) @@ -191,13 +99,3 @@ export default class MobileLayout { return rootContainer; } } - -function FilePropertiesWrapper() { - const { note, ntxId } = useNoteContext(); - - return ( -
- {note?.type === "file" && } -
- ); -} diff --git a/apps/client/src/menus/context_menu.ts b/apps/client/src/menus/context_menu.ts index 986ea94c48..415c0a2c6a 100644 --- a/apps/client/src/menus/context_menu.ts +++ b/apps/client/src/menus/context_menu.ts @@ -248,7 +248,7 @@ class ContextMenu { if ("uiIcon" in item || "checked" in item) { const icon = (item.checked ? "bx bx-check" : item.uiIcon); if (icon) { - $icon.addClass(icon); + $icon.addClass([icon, "tn-icon"]); } else { $icon.append(" "); } diff --git a/apps/client/src/menus/launcher_context_menu.ts b/apps/client/src/menus/launcher_context_menu.ts index 717180690a..f4ae7a148f 100644 --- a/apps/client/src/menus/launcher_context_menu.ts +++ b/apps/client/src/menus/launcher_context_menu.ts @@ -1,12 +1,12 @@ -import treeService from "../services/tree.js"; -import froca from "../services/froca.js"; -import contextMenu, { type MenuCommandItem, type MenuItem } from "./context_menu.js"; -import dialogService from "../services/dialog.js"; -import server from "../services/server.js"; -import { t } from "../services/i18n.js"; +import type { ContextMenuCommandData,FilteredCommandNames } from "../components/app_context.js"; import type { SelectMenuItemEventListener } from "../components/events.js"; +import dialogService from "../services/dialog.js"; +import froca from "../services/froca.js"; +import { t } from "../services/i18n.js"; +import server from "../services/server.js"; +import treeService from "../services/tree.js"; import type NoteTreeWidget from "../widgets/note_tree.js"; -import type { FilteredCommandNames, ContextMenuCommandData } from "../components/app_context.js"; +import contextMenu, { type MenuCommandItem, type MenuItem } from "./context_menu.js"; type LauncherCommandNames = FilteredCommandNames; @@ -32,8 +32,8 @@ export default class LauncherContextMenu implements SelectMenuItemEventListener< const note = this.node.data.noteId ? await froca.getNote(this.node.data.noteId) : null; const parentNoteId = this.node.getParent().data.noteId; - const isVisibleRoot = note?.noteId === "_lbVisibleLaunchers"; - const isAvailableRoot = note?.noteId === "_lbAvailableLaunchers"; + const isVisibleRoot = note?.noteId === "_lbVisibleLaunchers" || note?.noteId === "_lbMobileVisibleLaunchers"; + const isAvailableRoot = note?.noteId === "_lbAvailableLaunchers" || note?.noteId === "_lbMobileAvailableLaunchers"; const isVisibleItem = parentNoteId === "_lbVisibleLaunchers" || parentNoteId === "_lbMobileVisibleLaunchers"; const isAvailableItem = parentNoteId === "_lbAvailableLaunchers" || parentNoteId === "_lbMobileAvailableLaunchers"; const isItem = isVisibleItem || isAvailableItem; diff --git a/apps/client/src/print.tsx b/apps/client/src/print.tsx index 96461db2dc..dc7817d9b5 100644 --- a/apps/client/src/print.tsx +++ b/apps/client/src/print.tsx @@ -18,6 +18,10 @@ export type PrintReport = { } | { type: "collection"; ignoredNoteIds: string[]; +} | { + type: "error"; + message: string; + stack?: string; }; async function main() { diff --git a/apps/client/src/services/attributes.ts b/apps/client/src/services/attributes.ts index 2bff933244..77558c9464 100644 --- a/apps/client/src/services/attributes.ts +++ b/apps/client/src/services/attributes.ts @@ -168,6 +168,49 @@ function isAffecting(attrRow: AttributeRow, affectedNote: FNote | null | undefin return false; } +/** + * Toggles whether a dangerous attribute is enabled or not. When an attribute is disabled, its name is prefixed with `disabled:`. + * + * Note that this work for non-dangerous attributes as well. + * + * If there are multiple attributes with the same name, all of them will be toggled at the same time. + * + * @param note the note whose attribute to change. + * @param type the type of dangerous attribute (label or relation). + * @param name the name of the dangerous attribute. + * @param willEnable whether to enable or disable the attribute. + * @returns a promise that will resolve when the request to the server completes. + */ +async function toggleDangerousAttribute(note: FNote, type: "label" | "relation", name: string, willEnable: boolean) { + const attrs = [ + ...note.getOwnedAttributes(type, name), + ...note.getOwnedAttributes(type, `disabled:${name}`) + ]; + + for (const attr of attrs) { + const baseName = getNameWithoutDangerousPrefix(attr.name); + const newName = willEnable ? baseName : `disabled:${baseName}`; + if (newName === attr.name) continue; + + // We are adding and removing afterwards to avoid a flicker (because for a moment there would be no active content attribute anymore) because the operations are done in sequence and not atomically. + if (attr.type === "label") { + await setLabel(note.noteId, newName, attr.value); + } else { + await setRelation(note.noteId, newName, attr.value); + } + await removeAttributeById(note.noteId, attr.attributeId); + } +} + +/** + * Returns the name of an attribute without the `disabled:` prefix, or the same name if it's not disabled. + * @param name the name of an attribute. + * @returns the name without the `disabled:` prefix. + */ +function getNameWithoutDangerousPrefix(name: string) { + return name.startsWith("disabled:") ? name.substring(9) : name; +} + export default { addLabel, setLabel, @@ -177,5 +220,7 @@ export default { removeAttributeById, removeOwnedLabelByName, removeOwnedRelationByName, - isAffecting + isAffecting, + toggleDangerousAttribute, + getNameWithoutDangerousPrefix }; diff --git a/apps/client/src/services/bundle.ts b/apps/client/src/services/bundle.ts index d33ba76a0a..7cee01812b 100644 --- a/apps/client/src/services/bundle.ts +++ b/apps/client/src/services/bundle.ts @@ -2,7 +2,6 @@ import { h, VNode } from "preact"; import BasicWidget, { ReactWrappedWidget } from "../widgets/basic_widget.js"; import RightPanelWidget from "../widgets/right_panel_widget.js"; -import froca from "./froca.js"; import type { Entity } from "./frontend_script_api.js"; import { WidgetDefinitionWithType } from "./frontend_script_api_preact.js"; import { t } from "./i18n.js"; @@ -38,15 +37,18 @@ async function getAndExecuteBundle(noteId: string, originEntity = null, script = export type ParentName = "left-pane" | "center-pane" | "note-detail-pane" | "right-pane"; -export async function executeBundle(bundle: Bundle, originEntity?: Entity | null, $container?: JQuery) { +export async function executeBundleWithoutErrorHandling(bundle: Bundle, originEntity?: Entity | null, $container?: JQuery) { const apiContext = await ScriptContext(bundle.noteId, bundle.allNoteIds, originEntity, $container); + return await function () { + return eval(`const apiContext = this; (async function() { ${bundle.script}\r\n})()`); + }.call(apiContext); +} +export async function executeBundle(bundle: Bundle, originEntity?: Entity | null, $container?: JQuery) { try { - return await function () { - return eval(`const apiContext = this; (async function() { ${bundle.script}\r\n})()`); - }.call(apiContext); - } catch (e: any) { - showErrorForScriptNote(bundle.noteId, t("toast.bundle-error.message", { message: e.message })); + return await executeBundleWithoutErrorHandling(bundle, originEntity, $container); + } catch (e: unknown) { + showErrorForScriptNote(bundle.noteId, t("toast.bundle-error.message", { message: getErrorMessage(e) })); logError("Widget initialization failed: ", e); } } diff --git a/apps/client/src/services/content_renderer.css b/apps/client/src/services/content_renderer.css new file mode 100644 index 0000000000..80764486d4 --- /dev/null +++ b/apps/client/src/services/content_renderer.css @@ -0,0 +1,9 @@ +.rendered-content.no-preview > div { + display: flex; + flex-direction: column; + justify-content: space-around; + align-items: center; + height: 100%; + font-size: 500%; + flex-grow: 1; +} diff --git a/apps/client/src/services/content_renderer.ts b/apps/client/src/services/content_renderer.ts index 4fbf51024c..148d59acd0 100644 --- a/apps/client/src/services/content_renderer.ts +++ b/apps/client/src/services/content_renderer.ts @@ -1,3 +1,5 @@ +import "./content_renderer.css"; + import { normalizeMimeTypeForCKEditor } from "@triliumnext/commons"; import WheelZoom from 'vanilla-js-wheel-zoom'; @@ -13,7 +15,7 @@ import protectedSessionService from "./protected_session.js"; import protectedSessionHolder from "./protected_session_holder.js"; import renderService from "./render.js"; import { applySingleBlockSyntaxHighlight } from "./syntax_highlight.js"; -import utils from "./utils.js"; +import utils, { getErrorMessage } from "./utils.js"; let idCounter = 1; @@ -60,7 +62,10 @@ export async function getRenderedContent(this: {} | { ctx: string }, entity: FNo } else if (type === "render" && entity instanceof FNote) { const $content = $("
"); - await renderService.render(entity, $content); + await renderService.render(entity, $content, (e) => { + const $error = $("
").addClass("admonition caution").text(typeof e === "string" ? e : getErrorMessage(e)); + $content.empty().append($error); + }); $renderedContent.append($content); } else if (type === "doc" && "noteId" in entity) { @@ -71,18 +76,9 @@ export async function getRenderedContent(this: {} | { ctx: string }, entity: FNo $renderedContent.append($("
").append("
This note is protected and to access it you need to enter password.
").append("
").append($button)); } else if (entity instanceof FNote) { - $renderedContent - .css("display", "flex") - .css("flex-direction", "column"); + $renderedContent.addClass("no-preview"); $renderedContent.append( - $("
") - .css("display", "flex") - .css("justify-content", "space-around") - .css("align-items", "center") - .css("height", "100%") - .css("font-size", "500%") - .css("flex-grow", "1") - .append($("").addClass(entity.getIcon())) + $("
").append($("").addClass(entity.getIcon())) ); if (entity.type === "webView" && entity.hasLabel("webViewSrc")) { @@ -292,10 +288,11 @@ function getRenderingType(entity: FNote | FAttachment) { } const mime = "mime" in entity && entity.mime; + const isIconPack = entity instanceof FNote && entity.hasLabel("iconPack"); if (type === "file" && mime === "application/pdf") { type = "pdf"; - } else if ((type === "file" || type === "viewConfig") && mime && CODE_MIME_TYPES.has(mime)) { + } else if ((type === "file" || type === "viewConfig") && mime && CODE_MIME_TYPES.has(mime) && !isIconPack) { type = "code"; } else if (type === "file" && mime && mime.startsWith("audio/")) { type = "audio"; diff --git a/apps/client/src/services/experimental_features.ts b/apps/client/src/services/experimental_features.ts index 62d4ebb053..8cfbe126e8 100644 --- a/apps/client/src/services/experimental_features.ts +++ b/apps/client/src/services/experimental_features.ts @@ -1,5 +1,6 @@ import { t } from "./i18n"; import options from "./options"; +import { isMobile } from "./utils"; export interface ExperimentalFeature { id: string; @@ -21,7 +22,7 @@ let enabledFeatures: Set | null = null; export function isExperimentalFeatureEnabled(featureId: ExperimentalFeatureId): boolean { if (featureId === "new-layout") { - return options.is("newLayout"); + return (isMobile() || options.is("newLayout")); } return getEnabledFeatures().has(featureId); @@ -29,7 +30,7 @@ export function isExperimentalFeatureEnabled(featureId: ExperimentalFeatureId): export function getEnabledExperimentalFeatureIds() { const values = [ ...getEnabledFeatures().values() ]; - if (options.is("newLayout")) { + if (isMobile() || options.is("newLayout")) { values.push("new-layout"); } return values; diff --git a/apps/client/src/services/i18n.ts b/apps/client/src/services/i18n.ts index 5b5f38b762..c8bb9097d7 100644 --- a/apps/client/src/services/i18n.ts +++ b/apps/client/src/services/i18n.ts @@ -24,7 +24,8 @@ export async function initLocale() { backend: { loadPath: `${window.glob.assetPath}/translations/{{lng}}/{{ns}}.json` }, - returnEmptyString: false + returnEmptyString: false, + showSupportNotice: false }); await setDayjsLocale(locale); diff --git a/apps/client/src/services/note_tooltip.ts b/apps/client/src/services/note_tooltip.ts index 60af420468..23263966e2 100644 --- a/apps/client/src/services/note_tooltip.ts +++ b/apps/client/src/services/note_tooltip.ts @@ -1,20 +1,20 @@ -import treeService from "./tree.js"; -import linkService from "./link.js"; -import froca from "./froca.js"; -import utils from "./utils.js"; -import attributeRenderer from "./attribute_renderer.js"; -import contentRenderer from "./content_renderer.js"; import appContext from "../components/app_context.js"; import type FNote from "../entities/fnote.js"; +import attributeRenderer from "./attribute_renderer.js"; +import contentRenderer from "./content_renderer.js"; +import froca from "./froca.js"; import { t } from "./i18n.js"; +import linkService from "./link.js"; +import treeService from "./tree.js"; +import utils from "./utils.js"; // Track all elements that open tooltips let openTooltipElements: JQuery[] = []; let dismissTimer: ReturnType; function setupGlobalTooltip() { - $(document).on("mouseenter", "a:not(.no-tooltip-preview)", mouseEnterHandler); - $(document).on("mouseenter", "[data-href]:not(.no-tooltip-preview)", mouseEnterHandler); + $(document).on("pointerenter", "a:not(.no-tooltip-preview)", mouseEnterHandler); + $(document).on("pointerenter", "[data-href]:not(.no-tooltip-preview)", mouseEnterHandler); // close any note tooltip after click, this fixes the problem that sometimes tooltips remained on the screen $(document).on("click", (e) => { @@ -37,10 +37,12 @@ function dismissAllTooltips() { } function setupElementTooltip($el: JQuery) { - $el.on("mouseenter", mouseEnterHandler); + $el.on("pointerenter", mouseEnterHandler); } -async function mouseEnterHandler(this: HTMLElement) { +async function mouseEnterHandler(this: HTMLElement, e: JQuery.TriggeredEvent) { + if (e.pointerType !== "mouse") return; + const $link = $(this); if ($link.hasClass("no-tooltip-preview") || $link.hasClass("disabled")) { @@ -91,7 +93,7 @@ async function mouseEnterHandler(this: HTMLElement) { } const html = `
${content}
`; - const tooltipClass = "tooltip-" + Math.floor(Math.random() * 999_999_999); + const tooltipClass = `tooltip-${ Math.floor(Math.random() * 999_999_999)}`; // we need to check if we're still hovering over the element // since the operation to get tooltip content was async, it is possible that @@ -224,7 +226,7 @@ function renderFootnoteOrAnchor($link: JQuery, url: string) { } let footnoteContent = $targetContent.html(); - footnoteContent = `
${footnoteContent}
` + footnoteContent = `
${footnoteContent}
`; return footnoteContent || ""; } diff --git a/apps/client/src/services/render.ts b/apps/client/src/services/render.ts deleted file mode 100644 index adfd8a4949..0000000000 --- a/apps/client/src/services/render.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { h, VNode } from "preact"; - -import type FNote from "../entities/fnote.js"; -import { renderReactWidgetAtElement } from "../widgets/react/react_utils.jsx"; -import bundleService, { type Bundle } from "./bundle.js"; -import froca from "./froca.js"; -import server from "./server.js"; - -async function render(note: FNote, $el: JQuery) { - const relations = note.getRelations("renderNote"); - const renderNoteIds = relations.map((rel) => rel.value).filter((noteId) => noteId); - - $el.empty().toggle(renderNoteIds.length > 0); - - for (const renderNoteId of renderNoteIds) { - const bundle = await server.post(`script/bundle/${renderNoteId}`); - - const $scriptContainer = $("
"); - $el.append($scriptContainer); - - $scriptContainer.append(bundle.html); - - // async so that scripts cannot block trilium execution - bundleService.executeBundle(bundle, note, $scriptContainer).then(result => { - // Render JSX - if (bundle.html === "") { - renderIfJsx(bundle, result, $el); - } - }); - } - - return renderNoteIds.length > 0; -} - -async function renderIfJsx(bundle: Bundle, result: unknown, $el: JQuery) { - // Ensure the root script note is actually a JSX. - const rootScriptNoteId = await froca.getNote(bundle.noteId); - if (rootScriptNoteId?.mime !== "text/jsx") return; - - // Ensure the output is a valid el. - if (typeof result !== "function") return; - - // Obtain the parent component. - const closestComponent = glob.getComponentByEl($el.closest(".component")[0]); - if (!closestComponent) return; - - // Render the element. - const el = h(result as () => VNode, {}); - renderReactWidgetAtElement(closestComponent, el, $el[0]); -} - -export default { - render -}; diff --git a/apps/client/src/services/render.tsx b/apps/client/src/services/render.tsx new file mode 100644 index 0000000000..682efa8871 --- /dev/null +++ b/apps/client/src/services/render.tsx @@ -0,0 +1,86 @@ +import { Component, h, VNode } from "preact"; + +import type FNote from "../entities/fnote.js"; +import { renderReactWidgetAtElement } from "../widgets/react/react_utils.jsx"; +import { type Bundle, executeBundleWithoutErrorHandling } from "./bundle.js"; +import froca from "./froca.js"; +import server from "./server.js"; + +type ErrorHandler = (e: unknown) => void; + +async function render(note: FNote, $el: JQuery, onError?: ErrorHandler) { + const relations = note.getRelations("renderNote"); + const renderNoteIds = relations.map((rel) => rel.value).filter((noteId) => noteId); + + $el.empty().toggle(renderNoteIds.length > 0); + + try { + for (const renderNoteId of renderNoteIds) { + const bundle = await server.postWithSilentInternalServerError(`script/bundle/${renderNoteId}`); + + const $scriptContainer = $("
"); + $el.append($scriptContainer); + + $scriptContainer.append(bundle.html); + + // async so that scripts cannot block trilium execution + executeBundleWithoutErrorHandling(bundle, note, $scriptContainer) + .catch(onError) + .then(result => { + // Render JSX + if (bundle.html === "") { + renderIfJsx(bundle, result, $el, onError).catch(onError); + } + }); + } + + return renderNoteIds.length > 0; + } catch (e) { + if (typeof e === "string" && e.startsWith("{") && e.endsWith("}")) { + try { + onError?.(JSON.parse(e)); + } catch (e) { + onError?.(e); + } + } else { + onError?.(e); + } + } +} + +async function renderIfJsx(bundle: Bundle, result: unknown, $el: JQuery, onError?: ErrorHandler) { + // Ensure the root script note is actually a JSX. + const rootScriptNoteId = await froca.getNote(bundle.noteId); + if (rootScriptNoteId?.mime !== "text/jsx") return; + + // Ensure the output is a valid el. + if (typeof result !== "function") return; + + // Obtain the parent component. + const closestComponent = glob.getComponentByEl($el.closest(".component")[0]); + if (!closestComponent) return; + + // Render the element. + const UserErrorBoundary = class UserErrorBoundary extends Component { + constructor(props: object) { + super(props); + this.state = { error: null }; + } + + componentDidCatch(error: unknown) { + onError?.(error); + this.setState({ error }); + } + + render() { + if ("error" in this.state && this.state?.error) return null; + return this.props.children; + } + }; + const el = h(UserErrorBoundary, {}, h(result as () => VNode, {})); + renderReactWidgetAtElement(closestComponent, el, $el[0]); +} + +export default { + render +}; diff --git a/apps/client/src/services/server.ts b/apps/client/src/services/server.ts index 381c58a3cf..fb1e598ec2 100644 --- a/apps/client/src/services/server.ts +++ b/apps/client/src/services/server.ts @@ -73,6 +73,10 @@ async function post(url: string, data?: unknown, componentId?: string) { return await call("POST", url, componentId, { data }); } +async function postWithSilentInternalServerError(url: string, data?: unknown, componentId?: string) { + return await call("POST", url, componentId, { data, silentInternalServerError: true }); +} + async function put(url: string, data?: unknown, componentId?: string) { return await call("PUT", url, componentId, { data }); } @@ -111,6 +115,7 @@ let maxKnownEntityChangeId = 0; interface CallOptions { data?: unknown; silentNotFound?: boolean; + silentInternalServerError?: boolean; // If `true`, the value will be returned as a string instead of a JavaScript object if JSON, XMLDocument if XML, etc. raw?: boolean; } @@ -143,7 +148,7 @@ async function call(method: string, url: string, componentId?: string, option }); })) as any; } else { - resp = await ajax(url, method, data, headers, !!options.silentNotFound, options.raw); + resp = await ajax(url, method, data, headers, options); } const maxEntityChangeIdStr = resp.headers["trilium-max-entity-change-id"]; @@ -155,10 +160,7 @@ async function call(method: string, url: string, componentId?: string, option return resp.body as T; } -/** - * @param raw if `true`, the value will be returned as a string instead of a JavaScript object if JSON, XMLDocument if XML, etc. - */ -function ajax(url: string, method: string, data: unknown, headers: Headers, silentNotFound: boolean, raw?: boolean): Promise { +function ajax(url: string, method: string, data: unknown, headers: Headers, opts: CallOptions): Promise { return new Promise((res, rej) => { const options: JQueryAjaxSettings = { url: window.glob.baseApiUrl + url, @@ -190,7 +192,9 @@ function ajax(url: string, method: string, data: unknown, headers: Headers, sile // don't report requests that are rejected by the browser, usually when the user is refreshing or going to a different page. rej("rejected by browser"); return; - } else if (silentNotFound && jqXhr.status === 404) { + } else if (opts.silentNotFound && jqXhr.status === 404) { + // report nothing + } else if (opts.silentInternalServerError && jqXhr.status === 500) { // report nothing } else { await reportError(method, url, jqXhr.status, jqXhr.responseText); @@ -200,7 +204,7 @@ function ajax(url: string, method: string, data: unknown, headers: Headers, sile } }; - if (raw) { + if (opts.raw) { options.dataType = "text"; } @@ -299,6 +303,7 @@ export default { get, getWithSilentNotFound, post, + postWithSilentInternalServerError, put, patch, remove, diff --git a/apps/client/src/stylesheets/style.css b/apps/client/src/stylesheets/style.css index 69632dd29e..8950f3fd3f 100644 --- a/apps/client/src/stylesheets/style.css +++ b/apps/client/src/stylesheets/style.css @@ -28,7 +28,7 @@ --bs-body-color: var(--main-text-color) !important; --bs-body-bg: var(--main-background-color) !important; --ck-mention-list-max-height: 500px; - --tn-modal-max-height: 90vh; + --tn-modal-max-height: 90svh; --tree-item-light-theme-max-color-lightness: 50; --tree-item-dark-theme-min-color-lightness: 75; @@ -111,6 +111,7 @@ body.mobile #root-widget.virtual-keyboard-opened #mobile-bottom-bar { } #mobile-bottom-bar { + border-top: 1px solid var(--main-border-color); padding-bottom: var(--mobile-bottom-offset); } @@ -152,6 +153,11 @@ textarea, background: var(--input-background-color); } +.form-control:disabled { + background-color: var(--input-background-color); + opacity: 0.6; +} + .form-control:focus { color: var(--input-text-color); background: var(--input-background-color); @@ -409,6 +415,7 @@ body.desktop .tabulator-popup-container, .dropdown-menu.static { box-shadow: unset; + backdrop-filter: unset !important; } .dropend .dropdown-toggle::after { @@ -454,7 +461,7 @@ body.desktop .tabulator-popup-container, visibility: hidden; } -body.desktop .dropdown-menu:not(#context-menu-container) .dropdown-item, +.dropdown-menu:not(#context-menu-container) .dropdown-item, body.desktop .dropdown-menu .dropdown-toggle, body #context-menu-container .dropdown-item > span, body.mobile .dropdown .dropdown-submenu > span { @@ -462,6 +469,15 @@ body.mobile .dropdown .dropdown-submenu > span { align-items: center; } + +body.mobile .dropdown .dropdown-submenu { + flex-wrap: wrap; + + & > span { + flex-grow: 1; + } +} + .dropdown-item span.keyboard-shortcut, .dropdown-item *:not(.keyboard-shortcut) > kbd { flex-grow: 1; @@ -931,6 +947,7 @@ table.promoted-attributes-in-tooltip th { color: var(--muted-text-color); opacity: 0.6; line-height: 1; + word-wrap: break-word; } .aa-dropdown-menu .aa-suggestion p { @@ -1325,15 +1342,12 @@ body.desktop .dropdown-submenu > .dropdown-menu { max-width: 300px; } -.dropdown-submenu.dropstart > .dropdown-menu { +.dropdown-submenu.dropstart > .dropdown-menu, +body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu { inset-inline-start: auto; inset-inline-end: calc(100% - 2px); } -body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu { - inset-inline-start: calc(-100% + 10px); -} - .right-dropdown-widget { flex-shrink: 0; } @@ -1530,7 +1544,8 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu { @media (max-width: 991px) { body.mobile #launcher-pane .dropdown.global-menu > .dropdown-menu.show, - body.mobile #launcher-container .dropdown > .dropdown-menu.show { + body.mobile #launcher-container .dropdown > .dropdown-menu.show, + body.mobile .dropdown-menu.mobile-bottom-menu.show { --dropdown-bottom: calc(var(--mobile-bottom-offset) + var(--launcher-pane-size)); position: fixed !important; bottom: var(--dropdown-bottom) !important; @@ -1542,6 +1557,16 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu { max-height: calc(var(--tn-modal-max-height) - var(--dropdown-bottom)); } + body.mobile #launcher-container .dropdown > .dropdown-menu.show { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + } + + body.mobile .dropdown-menu.mobile-bottom-menu.show { + --dropdown-bottom: 0px; + padding-bottom: calc(max(var(--menu-padding-size), env(safe-area-inset-bottom))) !important; + } + #mobile-sidebar-container { position: fixed; top: 0; @@ -1562,7 +1587,7 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu { position: absolute; top: 0; inset-inline-start: 0; - bottom: 0; + height: 100dvh; width: 85vw; padding-top: env(safe-area-inset-top); transition: transform 250ms ease-in-out; @@ -1626,13 +1651,27 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu { word-break: break-all; } - body.mobile .jump-to-note-dialog .modal-content { - overflow-y: auto; - } + body.mobile .jump-to-note-dialog { + .modal-header { + padding-bottom: 0.75rem !important; + } - body.mobile .jump-to-note-dialog .modal-dialog .aa-dropdown-menu { - max-height: unset; - overflow: auto; + .modal-content { + padding-bottom: 0 !important; + } + + .modal-body { + overflow-y: auto; + } + + .aa-dropdown-menu { + max-height: unset; + overflow: auto; + } + + .aa-suggestion { + padding-inline: 0; + } } body.mobile .modal-dialog .dropdown-menu { @@ -1667,47 +1706,15 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu { background: var(--main-background-color); } - .modal-dialog { - margin: var(--bs-modal-margin); - max-width: 80%; - } + body.mobile { + .modal-dialog { + margin: var(--bs-modal-margin); + max-width: 80%; + } - .modal-content { - height: 100%; - } -} - -@media (max-width: 991px) { - body.mobile.force-fixed-tree #mobile-sidebar-wrapper { - padding-top: 0; - position: static; - height: 40vh; - width: 100vw; - transform: none !important; - background-color: var(--left-pane-background-color) !important; - border-bottom: 0.5px solid var(--main-border-color); - } - - body.mobile.force-fixed-tree #mobile-sidebar-container { - display: none !important; - } - - body.mobile.force-fixed-tree #mobile-sidebar-wrapper .quick-search { - display: none; - } - - body.mobile.force-fixed-tree .component > button.bx-sidebar { - visibility: hidden; - padding: 0; - width: 6px; - } - - body.mobile.force-fixed-tree #mobile-rest-container { - flex-direction: column !important; - } - - body.mobile.force-fixed-tree #detail-container { - flex-grow: 1; + .modal-content { + height: 100%; + } } } @@ -2623,14 +2630,14 @@ iframe.print-iframe { } } - #root-widget.virtual-keyboard-opened .note-split:not(:focus-within) { + #root-widget.virtual-keyboard-opened .note-split:not(.active) { max-height: 80px; opacity: 0.4; } } } -body.desktop .title-row { +.title-row { height: 50px; min-height: 50px; align-items: center; diff --git a/apps/client/src/stylesheets/theme-next-dark.css b/apps/client/src/stylesheets/theme-next-dark.css index 80acfe2e0a..dfdc209040 100644 --- a/apps/client/src/stylesheets/theme-next-dark.css +++ b/apps/client/src/stylesheets/theme-next-dark.css @@ -134,6 +134,7 @@ --left-pane-collapsed-border-color: #0009; --left-pane-background-color: #1f1f1f; --left-pane-text-color: #aaaaaa; + --left-pane-icon-color: #c5c5c5; --left-pane-item-hover-background: #ffffff0d; --left-pane-item-selected-background: #ffffff25; --left-pane-item-selected-color: #dfdfdf; @@ -209,6 +210,7 @@ --badge-share-background-color: #4d4d4d; --badge-clipped-note-background-color: #295773; --badge-execute-background-color: #604180; + --badge-active-content-background-color: rgb(12, 68, 70); --note-icon-background-color: #444444; --note-icon-color: #d4d4d4; @@ -237,9 +239,9 @@ --bottom-panel-background-color: #11111180; --bottom-panel-title-bar-background-color: #3F3F3F80; - + --status-bar-border-color: var(--main-border-color); - + --scrollbar-thumb-color: #fdfdfd5c; --scrollbar-thumb-hover-color: #ffffff7d; --scrollbar-background-color: transparent; @@ -289,6 +291,15 @@ --ck-editor-toolbar-button-on-shadow: 1px 1px 2px rgba(0, 0, 0, .75); --ck-editor-toolbar-dropdown-button-open-background: #ffffff14; + --note-list-view-icon-color: var(--left-pane-icon-color); + --note-list-view-large-icon-background: var(--note-icon-background-color); + --note-list-view-large-icon-color: var(--note-icon-color); + --note-list-view-search-result-highlight-background: transparent; + --note-list-view-search-result-highlight-color: var(--quick-search-result-highlight-color); + --note-list-view-content-background: rgba(0, 0, 0, .2); + --note-list-view-content-search-result-highlight-background: var(--quick-search-result-highlight-color); + --note-list-view-content-search-result-highlight-color: black; + --calendar-coll-event-background-saturation: 25%; --calendar-coll-event-background-lightness: 20%; --calendar-coll-event-background-color: #3c3c3c; @@ -302,7 +313,8 @@ * Dark color scheme tweaks */ -#left-pane .fancytree-node.tinted { +#left-pane .fancytree-node.tinted, +.nested-note-list-item.use-note-color { --custom-color: var(--dark-theme-custom-color); /* The background color of the active item in the note tree. @@ -336,12 +348,24 @@ body .todo-list input[type="checkbox"]:not(:checked):before { --promoted-attribute-card-background-color: hsl(var(--custom-color-hue), 13.2%, 20.8%); } +.modal.tab-bar-modal .tabs .tab-card.with-hue { + background-color: hsl(var(--bg-hue), 8.8%, 11.2%); + border-color: hsl(var(--bg-hue), 9.4%, 25.1%); +} + +.modal.tab-bar-modal .tabs .tab-card.active.with-hue { + background-color: hsl(var(--bg-hue), 8.8%, 16.2%); + border-color: hsl(var(--bg-hue), 9.4%, 25.1%); +} + + .use-note-color { --custom-color: var(--dark-theme-custom-color); } .note-split.with-hue, -.quick-edit-dialog-wrapper.with-hue { +.quick-edit-dialog-wrapper.with-hue, +.nested-note-list-item.with-hue { --note-icon-custom-background-color: hsl(var(--custom-color-hue), 15.8%, 30.9%); --note-icon-custom-color: hsl(var(--custom-color-hue), 100%, 76.5%); --note-icon-hover-custom-background-color: hsl(var(--custom-color-hue), 28.3%, 36.7%); @@ -350,4 +374,4 @@ body .todo-list input[type="checkbox"]:not(:checked):before { .note-split.with-hue *::selection, .quick-edit-dialog-wrapper.with-hue *::selection { --selection-background-color: hsl(var(--custom-color-hue), 49.2%, 35%); -} \ No newline at end of file +} diff --git a/apps/client/src/stylesheets/theme-next-light.css b/apps/client/src/stylesheets/theme-next-light.css index 1e50200d9a..4b6b37718c 100644 --- a/apps/client/src/stylesheets/theme-next-light.css +++ b/apps/client/src/stylesheets/theme-next-light.css @@ -127,6 +127,7 @@ --left-pane-collapsed-border-color: #0000000d; --left-pane-background-color: #f2f2f2; --left-pane-text-color: #383838; + --left-pane-icon-color: currentColor; --left-pane-item-hover-background: rgba(0, 0, 0, 0.032); --left-pane-item-selected-background: white; --left-pane-item-selected-color: black; @@ -201,6 +202,7 @@ --badge-share-background-color: #6b6b6b; --badge-clipped-note-background-color: #2284c0; --badge-execute-background-color: #7b47af; + --badge-active-content-background-color: rgb(27, 164, 168); --note-icon-background-color: #4f4f4f; --note-icon-color: white; @@ -287,6 +289,15 @@ --ck-editor-toolbar-button-on-shadow: none; --ck-editor-toolbar-dropdown-button-open-background: #0000000f; + --note-list-view-icon-color: var(--left-pane-icon-color); + --note-list-view-large-icon-background: var(--note-icon-background-color); + --note-list-view-large-icon-color: var(--note-icon-color); + --note-list-view-search-result-highlight-background: transparent; + --note-list-view-search-result-highlight-color: var(--quick-search-result-highlight-color); + --note-list-view-content-background: #b1b1b133; + --note-list-view-content-search-result-highlight-background: var(--quick-search-result-highlight-color); + --note-list-view-content-search-result-highlight-color: white; + --calendar-coll-event-background-lightness: 95%; --calendar-coll-event-background-saturation: 80%; --calendar-coll-event-background-color: #eaeaea; @@ -296,7 +307,8 @@ --calendar-coll-today-background-color: #00000006; } -#left-pane .fancytree-node.tinted { +#left-pane .fancytree-node.tinted, +.nested-note-list-item.use-note-color { --custom-color: var(--light-theme-custom-color); /* The background color of the active item in the note tree. @@ -311,8 +323,19 @@ --promoted-attribute-card-background-color: hsl(var(--custom-color-hue), 40%, 88%); } +.modal.tab-bar-modal .tabs .tab-card.with-hue { + background-color: hsl(var(--bg-hue), 56%, 96%); + border-color: hsl(var(--bg-hue), 33%, 41%); +} + +.modal.tab-bar-modal .tabs .tab-card.active.with-hue { + background-color: hsl(var(--bg-hue), 86%, 96%); + border-color: hsl(var(--bg-hue), 33%, 41%); +} + .note-split.with-hue, -.quick-edit-dialog-wrapper.with-hue { +.quick-edit-dialog-wrapper.with-hue, +.nested-note-list-item.with-hue { --note-icon-custom-background-color: hsl(var(--custom-color-hue), 44.5%, 43.1%); --note-icon-custom-color: hsl(var(--custom-color-hue), 91.3%, 91%); --note-icon-hover-custom-background-color: hsl(var(--custom-color-hue), 55.1%, 50.2%); @@ -321,4 +344,4 @@ .note-split.with-hue *::selection, .quick-edit-dialog-wrapper.with-hue *::selection { --selection-background-color: hsl(var(--custom-color-hue), 60%, 90%); -} \ No newline at end of file +} diff --git a/apps/client/src/stylesheets/theme-next/base.css b/apps/client/src/stylesheets/theme-next/base.css index 69f77569db..9e39b2f002 100644 --- a/apps/client/src/stylesheets/theme-next/base.css +++ b/apps/client/src/stylesheets/theme-next/base.css @@ -800,3 +800,18 @@ li.dropdown-item a.dropdown-item-button:focus-visible { background: var(--hover-item-background-color); color: var(--hover-item-text-color); } + +/* + * Alert bars + */ + +div.alert { + margin-bottom: 8px; + background: var(--alert-bar-background) !important; + border-radius: 8px; + font-size: .85em; +} + +div.alert p + p { + margin-block: 1em 0; +} \ No newline at end of file diff --git a/apps/client/src/stylesheets/theme-next/forms.css b/apps/client/src/stylesheets/theme-next/forms.css index 12f361c2f2..cbe5f2cda0 100644 --- a/apps/client/src/stylesheets/theme-next/forms.css +++ b/apps/client/src/stylesheets/theme-next/forms.css @@ -84,6 +84,22 @@ button.btn.btn-success kbd { letter-spacing: 0.5pt; } +/* + * Low profile buttons + */ + +button.tn-low-profile { + appearance: none; + background: transparent; + border: 0; + border-radius: 8px; + color: inherit; +} + +button.tn-low-profile:hover { + background-color: var(--icon-button-hover-background); +} + /* * Icon buttons */ @@ -129,6 +145,10 @@ button.btn.btn-success kbd { font-size: calc(var(--icon-button-size) * var(--icon-button-icon-ratio)); } +:root .icon-action.disabled::before { + opacity: .5; +} + :root .icon-action:not(.global-menu-button):hover, :root .icon-action:not(.global-menu-button).show, :root .tn-tool-button:hover, @@ -794,3 +814,35 @@ input[type="range"] { scrollbar-width: unset; } } + +/* + * Centered forms + */ + +.tn-centered-form { + display: flex; + flex-direction: column; + align-items: center; + margin-bottom: 20vh; +} + +.tn-centered-form .form-group { + text-align: center; + color: var(--muted-text-color); +} + +.tn-centered-form .form-icon { + font-size: 140px; + color: var(--main-border-color); +} + +.tn-centered-form .protected-session-password { + margin-inline: auto; + max-width: 350px; + text-align: center; +} + +.tn-centered-form .input-group, +.tn-centered-form button { + margin-top: 12px; +} diff --git a/apps/client/src/stylesheets/theme-next/notes/text.css b/apps/client/src/stylesheets/theme-next/notes/text.css index dc025bb66d..e025b23fb2 100644 --- a/apps/client/src/stylesheets/theme-next/notes/text.css +++ b/apps/client/src/stylesheets/theme-next/notes/text.css @@ -47,9 +47,14 @@ } /* The toolbar show / hide button for the current text block */ -.ck.ck-block-toolbar-button { +:root .ck.ck-block-toolbar-button { + --ck-color-block-toolbar-button: var(--muted-text-color); --ck-color-button-on-background: transparent; - --ck-color-button-on-color: currentColor; + --ck-color-button-on-color: var(--ck-editor-toolbar-button-on-color); + translate: -40% 0; + min-width: 0; + padding: 0; + z-index: 1600; } :root .ck.ck-toolbar .ck-button:not(.ck-disabled):active, @@ -517,6 +522,10 @@ button.ck.ck-button:is(.ck-button-action, .ck-button-save, .ck-button-cancel).ck * EDITOR'S CONTENT */ +.note-detail-editable-text-editor > .ck-placeholder { + opacity: .5; +} + /* * Code Blocks */ diff --git a/apps/client/src/stylesheets/theme-next/pages.css b/apps/client/src/stylesheets/theme-next/pages.css index f323d00005..42a831bae7 100644 --- a/apps/client/src/stylesheets/theme-next/pages.css +++ b/apps/client/src/stylesheets/theme-next/pages.css @@ -57,12 +57,12 @@ height: 18px; } -/* +/* * SEARCH PAGE */ /* Button bar */ - .search-definition-widget .search-setting-table tbody:last-child div { + .search-definition-widget .search-setting-table .search-actions-container { justify-content: flex-end; gap: 8px; } @@ -143,7 +143,7 @@ /* * OPTIONS PAGES */ - + :root { --options-card-min-width: 500px; --options-card-max-width: 900px; @@ -156,6 +156,10 @@ --preferred-max-content-width: var(--options-card-max-width); } +.note-split.options .collection-properties { + visibility: hidden; +} + /* Create a gap at the top of the option pages */ .note-detail-content-widget-content.options>*:first-child { margin-top: var(--options-first-item-top-margin, 1em); @@ -261,13 +265,6 @@ body.desktop .options-section:not(.tn-no-card) { margin-bottom: 6px; } -.options-section .alert { - margin-bottom: 8px; - background: var(--alert-bar-background) !important; - border-radius: 8px; - font-size: .85em; -} - nav.options-section-tabs { min-width: var(--options-card-min-width); max-width: var(--options-card-max-width); @@ -331,4 +328,4 @@ nav.options-section-tabs + .options-section { .etapi-options-section div { height: auto !important; -} \ No newline at end of file +} diff --git a/apps/client/src/stylesheets/theme-next/shell.css b/apps/client/src/stylesheets/theme-next/shell.css index 7ff132e1af..1ac2f13e77 100644 --- a/apps/client/src/stylesheets/theme-next/shell.css +++ b/apps/client/src/stylesheets/theme-next/shell.css @@ -739,39 +739,35 @@ body[dir=rtl] #left-pane span.fancytree-node.protected > span.fancytree-custom-i transform: translateX(-25%); } -body.mobile .fancytree-expander::before, -body.mobile .fancytree-title, -body.mobile .fancytree-node > span { - font-size: 1rem !important; -} - @media (max-width: 991px) { body.mobile #mobile-sidebar-container { background-color: rgba(0, 0, 0, 0.5); } - body.mobile:not(.force-fixed-tree) #mobile-sidebar-wrapper { + body.mobile #mobile-sidebar-wrapper { border-top-right-radius: 12px; border-bottom-right-radius: 12px; border-inline-end: 1px solid var(--subtle-border-color); } } -#left-pane .fancytree-expander { +#left-pane .fancytree-expander, +.nested-note-list-item .note-expander { opacity: 0.65; transition: opacity 150ms ease-in; } -#left-pane .fancytree-expander:hover { +#left-pane .fancytree-expander:hover, +.nested-note-list-item .note-expander:hover { opacity: 1; transition: opacity 300ms ease-out; } #left-pane .fancytree-custom-icon { margin-top: 0; /* Use this to align the icon with the tree view item's caption */ + color: var(--custom-color, var(--left-pane-icon-color)); } - #left-pane span.fancytree-active .fancytree-title { font-weight: normal; } @@ -1272,7 +1268,7 @@ body.layout-horizontal #rest-pane > .classic-toolbar-widget { #center-pane .note-split { padding-top: 2px; background-color: var(--note-split-background-color, var(--main-background-color)); - transition: border-color 250ms ease-in; + transition: border-color 150ms ease-out; border: 2px solid transparent; } @@ -1322,7 +1318,7 @@ body.mobile .note-title { margin-inline-start: 0; } -.title-row { +body.desktop .title-row { /* Aligns the "Create new split" button with the note menu button (the three dots button) */ padding-inline-end: 3px; } diff --git a/apps/client/src/stylesheets/tree.css b/apps/client/src/stylesheets/tree.css index 7131f6ab04..8ed03215b1 100644 --- a/apps/client/src/stylesheets/tree.css +++ b/apps/client/src/stylesheets/tree.css @@ -206,6 +206,7 @@ span.fancytree-selected .fancytree-title { } span.fancytree-selected .fancytree-custom-icon::before { + font-family: "boxicons"; content: "\eb43"; border: 1px solid var(--main-border-color); border-radius: 3px; diff --git a/apps/client/src/translations/ar/translation.json b/apps/client/src/translations/ar/translation.json index 296a0fdc86..1321d6ebe1 100644 --- a/apps/client/src/translations/ar/translation.json +++ b/apps/client/src/translations/ar/translation.json @@ -29,7 +29,9 @@ "widget-render-error": { "title": "فشل عرض عنصر واجهة مستخدم React مخصص" }, - "widget-missing-parent": "لا تحتوي الأداة المخصصة على خاصية إلزامية '{{property}}'.\n\nإذا كان من المفترض تشغيل هذا البرنامج النصي بدون عنصر واجهة مستخدم، فاستخدم '#run=frontendStartup' بدلاً من ذلك." + "widget-missing-parent": "لا تحتوي الأداة المخصصة على خاصية إلزامية '{{property}}'.\n\nإذا كان من المفترض تشغيل هذا البرنامج النصي بدون عنصر واجهة مستخدم، فاستخدم '#run=frontendStartup' بدلاً من ذلك.", + "open-script-note": "فتح ملاحظة برمجية", + "scripting-error": "خطأ في النص البرمجي المخصص: {{title}}" }, "add_link": { "add_link": "أضافة رابط", @@ -37,14 +39,19 @@ "search_note": "البحث عن الملاحظة بالاسم", "link_title": "عنوان الرابط", "button_add_link": "اضافة رابط", - "help_on_links": "مساعدة حول الارتباطات التشعبية" + "help_on_links": "مساعدة حول الارتباطات التشعبية", + "link_title_mirrors": "عنوان الرابط يعكس العنوان الحالي للملاحظة", + "link_title_arbitrary": "يمكن تغيير عنوان الرابط حسب الرغبة" }, "branch_prefix": { "edit_branch_prefix": "تعديل بادئة الفرع", "prefix": "البادئة: ", "save": "حفظ", "help_on_tree_prefix": "مساعدة حول بادئة الشجرة", - "branch_prefix_saved": "تم حفظ بادئة الفرع." + "branch_prefix_saved": "تم حفظ بادئة الفرع.", + "edit_branch_prefix_multiple": "تعديل البادئة لـ {{count}} من تفرعات الملاحظات", + "branch_prefix_saved_multiple": "تم حفظ بادئة التفرع لـ {{count}} من التفرعات.", + "affected_branches": "الفروع المتأثرة ({{count}}):" }, "bulk_actions": { "bulk_actions": "اجراءات جماعية", @@ -1173,9 +1180,6 @@ "note_not_found": "الملاحظة {{noteId}} غير موجودة!", "cannot_match_transform": "تعذر مطابقة التحويل: {{transform}}" }, - "web_view": { - "web_view": "عرض الويب" - }, "consistency_checks": { "title": "فحوصات التناسق" }, diff --git a/apps/client/src/translations/cn/translation.json b/apps/client/src/translations/cn/translation.json index 9dd25e5984..58ac0f748a 100644 --- a/apps/client/src/translations/cn/translation.json +++ b/apps/client/src/translations/cn/translation.json @@ -662,7 +662,8 @@ "show-cheatsheet": "显示快捷帮助", "toggle-zen-mode": "禅模式", "new-version-available": "新更新可用", - "download-update": "取得版本 {{latestVersion}}" + "download-update": "取得版本 {{latestVersion}}", + "search_notes": "搜索笔记" }, "zen_mode": { "button_exit": "退出禅模式" @@ -745,7 +746,7 @@ "button_title": "导出SVG格式图片" }, "relation_map_buttons": { - "create_child_note_title": "创建新的子笔记并添加到关系图", + "create_child_note_title": "创建子笔记并添加到图", "reset_pan_zoom_title": "重置平移和缩放到初始坐标和放大倍率", "zoom_in_title": "放大", "zoom_out_title": "缩小" @@ -759,7 +760,9 @@ "delete_this_note": "删除此笔记", "error_cannot_get_branch_id": "无法获取 notePath '{{notePath}}' 的 branchId", "error_unrecognized_command": "无法识别的命令 {{command}}", - "note_revisions": "笔记历史版本" + "note_revisions": "笔记历史版本", + "backlinks": "反链", + "content_language_switcher": "内容语言: {{language}}" }, "note_icon": { "change_note_icon": "更改笔记图标", @@ -910,7 +913,8 @@ "unknown_search_option": "未知的搜索选项 {{searchOptionName}}", "search_note_saved": "搜索笔记已保存到 {{- notePathTitle}}", "actions_executed": "操作已执行。", - "view_options": "查看选项:" + "view_options": "查看选项:", + "option": "选项" }, "similar_notes": { "title": "相似笔记", @@ -1004,7 +1008,7 @@ "no_attachments": "此笔记没有附件。" }, "book": { - "no_children_help": "此类型为书籍的笔记没有任何子笔记,因此没有内容显示。请参阅 wiki 了解详情。", + "no_children_help": "此集合没有任何子笔记,因此没有内容显示。", "drag_locked_title": "锁定编辑", "drag_locked_message": "无法拖拽,因为集合已被锁定编辑。" }, @@ -1060,15 +1064,6 @@ "default_new_note_title": "新笔记", "click_on_canvas_to_place_new_note": "点击画布以放置新笔记" }, - "render": { - "note_detail_render_help_1": "之所以显示此帮助说明,是因为这个类型为渲染 HTML 的笔记没有正常工作所需的关系。", - "note_detail_render_help_2": "渲染 HTML 笔记类型用于编写脚本。简而言之,您有一份 HTML 代码笔记(可包含一些 JavaScript),然后这个笔记会把页面渲染出来。要使其正常工作,您需要定义一个名为 \"renderNote\" 的关系指向要渲染的 HTML 笔记。" - }, - "web_view": { - "web_view": "网页视图", - "embed_websites": "网页视图类型的笔记允许您将网站嵌入到 Trilium 中。", - "create_label": "首先,请创建一个带有您要嵌入的 URL 地址的标签,例如 #webViewSrc=\"https://www.bing.com\"" - }, "backend_log": { "refresh": "刷新" }, @@ -1417,7 +1412,8 @@ "description": "描述", "reload_app": "重载应用以应用更改", "set_all_to_default": "将所有快捷键重置为默认值", - "confirm_reset": "您确定要将所有键盘快捷键重置为默认值吗?" + "confirm_reset": "您确定要将所有键盘快捷键重置为默认值吗?", + "no_results": "未找到与“{{filter}}”匹配的快捷方式" }, "spellcheck": { "title": "拼写检查", @@ -1618,7 +1614,9 @@ "print_report_title": "打印报告", "print_report_collection_content_other": "集合中的 {{count}} 篇笔记无法打印,因为它们不受支持或受到保护。", "print_report_collection_details_button": "查看详情", - "print_report_collection_details_ignored_notes": "忽略的笔记" + "print_report_collection_details_ignored_notes": "忽略的笔记", + "print_report_error_title": "打印失败", + "print_report_stack_trace": "堆栈跟踪" }, "note_title": { "placeholder": "请输入笔记标题...", @@ -1782,8 +1780,8 @@ "desktop-application": "桌面应用程序", "native-title-bar": "原生标题栏", "native-title-bar-description": "对于 Windows 和 macOS,关闭原生标题栏可使应用程序看起来更紧凑。在 Linux 上,保留原生标题栏可以更好地与系统集成。", - "background-effects": "启用背景效果(仅适用于 Windows 11)", - "background-effects-description": "Mica 效果为应用窗口添加模糊且时尚的背景,营造出深度感和现代外观。「原生标题栏」必須被禁用。", + "background-effects": "启用背景效果", + "background-effects-description": "为应用窗口添加模糊且时尚的背景,营造出深度感和现代外观。「原生标题栏」必須被禁用。", "restart-app-button": "重启应用程序以查看更改", "zoom-factor": "缩放系数" }, @@ -1802,7 +1800,8 @@ "geo-map": { "create-child-note-title": "创建一个新的子笔记并将其添加到地图中", "create-child-note-instruction": "单击地图以在该位置创建新笔记,或按 Escape 以取消。", - "unable-to-load-map": "无法加载地图。" + "unable-to-load-map": "无法加载地图。", + "create-child-note-text": "添加标记" }, "geo-map-context": { "open-location": "打开位置", @@ -2070,7 +2069,8 @@ "raster": "栅格", "vector_light": "矢量(浅色)", "vector_dark": "矢量(深色)", - "show-scale": "显示比例尺" + "show-scale": "显示比例尺", + "show-labels": "显示标记名称" }, "table_context_menu": { "delete_row": "删除行" @@ -2117,7 +2117,7 @@ }, "call_to_action": { "background_effects_title": "背景效果现已推出稳定版本", - "background_effects_message": "在 Windows 装置上,背景效果现在已完全稳定。背景效果通过模糊背后的背景,为使用者界面增添一抹色彩。此技术也用于其他应用程序,例如 Windows 资源管理器。", + "background_effects_message": "在 Windows 和 macOS 设备上,背景效果现在已稳定。背景效果通过模糊背后的背景,为使用者界面增添一抹色彩。", "background_effects_button": "启用背景效果", "next_theme_title": "试用新 Trilium 主题", "next_theme_message": "当前使用旧版主题,要试用新主题吗?", @@ -2149,7 +2149,6 @@ "app-restart-required": "(需重启程序以应用更改)" }, "pagination": { - "page_title": "第 {{startIndex}} 页 - 第 {{endIndex}} 页", "total_notes": "{{count}} 篇笔记" }, "collections": { @@ -2253,5 +2252,59 @@ "pages_alt": "第{{pageNumber}}页", "pages_loading": "加载中...", "layers_other": "{{count}} 层" + }, + "platform_indicator": { + "available_on": "在 {{platform}} 上可用" + }, + "mobile_tab_switcher": { + "title_other": "{{count}} 选项卡", + "more_options": "更多选项" + }, + "bookmark_buttons": { + "bookmarks": "书签" + }, + "web_view_setup": { + "title": "直接在 Trilium 中创建网页的实时视图", + "url_placeholder": "输入或粘贴网站地址,例如 https://triliumnotes.org", + "create_button": "创建网页视图", + "invalid_url_title": "无效的地址", + "invalid_url_message": "请输入有效的网址,例如 https://triliumnotes.org。", + "disabled_description": "此网页视图来自外部来源。为保护您免受网络钓鱼或恶意内容侵害,该视图不会自动加载。若您信任该来源,可手动启用加载功能。", + "disabled_button_enable": "启用网页视图" + }, + "render": { + "setup_title": "在此笔记中显示自定义 HTML 或 Preact JSX", + "setup_create_sample_preact": "使用 Preact 建立范例笔记", + "setup_create_sample_html": "使用 HTML 建立范例笔记", + "setup_sample_created": "已建立一个范例笔记作为子笔记。", + "disabled_description": "此渲染笔记来自外部来源。为保护您免受恶意内容侵害,该功能默认处于禁用状态。启用前请确保您信任该来源。", + "disabled_button_enable": "启用渲染笔记" + }, + "active_content_badges": { + "type_icon_pack": "图标包", + "type_backend_script": "后端脚本", + "type_frontend_script": "前端脚本", + "type_widget": "小部件", + "type_app_css": "自定义 CSS", + "type_render_note": "渲染笔记", + "type_web_view": "网页视图", + "type_app_theme": "自定义主题", + "toggle_tooltip_enable_tooltip": "点击以启用此 {{type}}。", + "toggle_tooltip_disable_tooltip": "点击以禁用此 {{type}}。", + "menu_docs": "打开文档", + "menu_execute_now": "立即执行脚本", + "menu_run": "自动执行", + "menu_run_disabled": "手动", + "menu_run_backend_startup": "当后端启动时", + "menu_run_hourly": "每小时", + "menu_run_daily": "每日", + "menu_run_frontend_startup": "当桌面前端启动时", + "menu_run_mobile_startup": "当移动前端启动时", + "menu_change_to_widget": "更改为小部件", + "menu_change_to_frontend_script": "更改为前端脚本", + "menu_theme_base": "主题基底" + }, + "setup_form": { + "more_info": "了解更多" } } diff --git a/apps/client/src/translations/de/translation.json b/apps/client/src/translations/de/translation.json index c250131841..9b8abcad8e 100644 --- a/apps/client/src/translations/de/translation.json +++ b/apps/client/src/translations/de/translation.json @@ -1,6 +1,6 @@ { "about": { - "title": "Über Trilium Notizen", + "title": "Über Trilium Notes", "homepage": "Startseite:", "app_version": "App-Version:", "db_version": "DB-Version:", @@ -662,7 +662,8 @@ "show-cheatsheet": "Cheatsheet anzeigen", "toggle-zen-mode": "Zen Modus", "new-version-available": "Neues Update verfügbar", - "download-update": "Version {{latestVersion}} herunterladen" + "download-update": "Version {{latestVersion}} herunterladen", + "search_notes": "Notizen durchsuchen" }, "sync_status": { "unknown": "

Der Synchronisations-Status wird bekannt, sobald der nächste Synchronisierungsversuch gestartet wird.

Klicke, um eine Synchronisierung jetzt auszulösen.

", @@ -742,7 +743,7 @@ "button_title": "Diagramm als SVG exportieren" }, "relation_map_buttons": { - "create_child_note_title": "Erstelle eine neue untergeordnete Notiz und füge sie dieser Beziehungskarte hinzu", + "create_child_note_title": "Erstelle eine untergeordnete Notiz und füge sie dieser Karte hinzu", "reset_pan_zoom_title": "Schwenken und Zoomen auf die ursprünglichen Koordinaten und Vergrößerung zurücksetzen", "zoom_in_title": "Hineinzoom", "zoom_out_title": "Herauszoomen" @@ -757,7 +758,9 @@ "delete_this_note": "Diese Notiz löschen", "error_cannot_get_branch_id": "BranchId für notePath „{{notePath}}“ kann nicht abgerufen werden", "error_unrecognized_command": "Unbekannter Befehl {{command}}", - "note_revisions": "Notiz Revisionen" + "note_revisions": "Notiz Revisionen", + "backlinks": "Rücklinks", + "content_language_switcher": "Inhaltssprache: {{language}}" }, "note_icon": { "change_note_icon": "Notiz-Icon ändern", @@ -909,7 +912,8 @@ "unknown_search_option": "Unbekannte Suchoption {{searchOptionName}}", "search_note_saved": "Suchnotiz wurde in {{-notePathTitle}} gespeichert", "actions_executed": "Aktionen wurden ausgeführt.", - "view_options": "Optionen anzeigen:" + "view_options": "Optionen anzeigen:", + "option": "Option" }, "similar_notes": { "title": "Ähnliche Notizen", @@ -1003,7 +1007,7 @@ "no_attachments": "Diese Notiz enthält keine Anhänge." }, "book": { - "no_children_help": "Diese Notiz mit dem Notiztyp Buch besitzt keine Unternotizen, deshalb ist nichts zum Anzeigen vorhanden. Siehe Wiki für mehr Details.", + "no_children_help": "Diese Sammlung enthält keineUnternotizen, daher gibt es nichts anzuzeigen.", "drag_locked_title": "Für Bearbeitung gesperrt", "drag_locked_message": "Das Ziehen ist nicht möglich, da die Sammlung für die Bearbeitung gesperrt ist." }, @@ -1059,15 +1063,6 @@ "default_new_note_title": "neue Notiz", "click_on_canvas_to_place_new_note": "Klicke auf den Canvas, um eine neue Notiz zu platzieren" }, - "render": { - "note_detail_render_help_1": "Diese Hilfesnotiz wird angezeigt, da diese Notiz vom Typ „HTML rendern“ nicht über die erforderliche Beziehung verfügt, um ordnungsgemäß zu funktionieren.", - "note_detail_render_help_2": "Render-HTML-Notiztyp wird benutzt für scripting. Kurzgesagt, du hast ein HTML-Code-Notiz (optional mit JavaScript) und diese Notiz rendert es. Damit es funktioniert, musst du eine a Beziehung namens \"renderNote\" zeigend auf die HTML-Notiz zum rendern definieren." - }, - "web_view": { - "web_view": "Webansicht", - "embed_websites": "Notiz vom Typ Web View ermöglicht das Einbetten von Websites in Trilium.", - "create_label": "Um zu beginnen, erstelle bitte ein Label mit einer URL-Adresse, die eingebettet werden soll, z. B. #webViewSrc=\"https://www.google.com\"" - }, "backend_log": { "refresh": "Aktualisieren" }, @@ -1383,7 +1378,8 @@ "description": "Beschreibung", "reload_app": "Lade die App neu, um die Änderungen zu übernehmen", "set_all_to_default": "Setze alle Verknüpfungen auf die Standardeinstellungen", - "confirm_reset": "Möchtest du wirklich alle Tastaturkürzel auf die Standardeinstellungen zurücksetzen?" + "confirm_reset": "Möchtest du wirklich alle Tastaturkürzel auf die Standardeinstellungen zurücksetzen?", + "no_results": "Keine Tastenkürzel für '{{filter}}' gefunden" }, "spellcheck": { "title": "Rechtschreibprüfung", @@ -1587,7 +1583,9 @@ "print_report_collection_details_button": "Details anzeigen", "print_report_collection_details_ignored_notes": "Ignorierte Notizen", "print_report_collection_content_one": "{{count}} Notiz in der Sammlung konnte nicht gedruckt werden, weil sie nicht unterstützt oder geschützt ist.", - "print_report_collection_content_other": "{{count}} Notizen in der Sammlung konnten nicht gedruckt werden, weil sie nicht unterstützt oder geschützt sind." + "print_report_collection_content_other": "{{count}} Notizen in der Sammlung konnten nicht gedruckt werden, weil sie nicht unterstützt oder geschützt sind.", + "print_report_error_title": "Druck fehlgeschlagen", + "print_report_stack_trace": "Stapelzurückverfolgung" }, "note_title": { "placeholder": "Titel der Notiz hier eingeben…", @@ -1771,7 +1769,8 @@ "geo-map": { "create-child-note-title": "Neue Unternotiz anlegen und zur Karte hinzufügen", "create-child-note-instruction": "Auf die Karte klicken, um eine neue Notiz an der Stelle zu erstellen oder Escape drücken um abzubrechen.", - "unable-to-load-map": "Karte konnte nicht geladen werden." + "unable-to-load-map": "Karte konnte nicht geladen werden.", + "create-child-note-text": "Marker hinzufügen" }, "geo-map-context": { "open-location": "Ort öffnen", @@ -2087,7 +2086,8 @@ "raster": "Raster", "vector_light": "Vektor (Hell)", "vector_dark": "Vektor (Dunkel)", - "show-scale": "Zeige Skalierung" + "show-scale": "Zeige Skalierung", + "show-labels": "Zeige Markierungsnamen" }, "table_context_menu": { "delete_row": "Zeile entfernen" @@ -2154,7 +2154,6 @@ "percentage": "%" }, "pagination": { - "page_title": "Seite {{startIndex}} von {{endIndex}}", "total_notes": "{{count}} Notizen" }, "collections": { @@ -2270,5 +2269,57 @@ }, "platform_indicator": { "available_on": "Verfügbar auf {{platform}}" + }, + "mobile_tab_switcher": { + "title_one": "{{count}} Tab", + "title_other": "{{count}} Tabs", + "more_options": "Weitere Optionen" + }, + "bookmark_buttons": { + "bookmarks": "Lesezeichen" + }, + "web_view_setup": { + "title": "Erstelle eine Live-Ansicht einer Webseite direkt in Trilium", + "url_placeholder": "Gib oder füge die Adresse der Webseite ein, zum Beispiel https://triliumnotes.org", + "create_button": "Erstelle Web Ansicht", + "invalid_url_title": "Ungültige Adresse", + "invalid_url_message": "Füge eine valide Webadresse ein, zum Beispiel https://triliumnotes.org.", + "disabled_description": "Diese Webansicht wurde von einer externen Quelle importiert. Um Sie vor Phishing oder schädlichen Inhalten zu schützen, wird sie nicht automatisch geladen. Sie können sie aktivieren, wenn Sie der Quelle vertrauen.", + "disabled_button_enable": "Webansicht aktivieren" + }, + "render": { + "setup_create_sample_html": "Eine Beispielnotiz mit HTML erstellen", + "setup_create_sample_preact": "Eine Beispielnotiz mit Preact erstellen", + "setup_title": "Benutzerdefiniertes HTML oder Preact JSX in dieser Notiz anzeigen", + "setup_sample_created": "Eine Beispielnotiz wurde als untergeordnete Notiz erstellt.", + "disabled_description": "Diese Rendering-Notizen stammen aus einer externen Quelle. Um Sie vor schädlichen Inhalten zu schützen, ist diese Funktion standardmäßig deaktiviert. Stellen Sie sicher, dass Sie der Quelle vertrauen, bevor Sie sie aktivieren.", + "disabled_button_enable": "Rendering-Notiz aktivieren" + }, + "active_content_badges": { + "type_icon_pack": "Icon-Paket", + "type_backend_script": "Backend-Skript", + "type_frontend_script": "Frontend-Skript", + "type_widget": "Widget", + "type_app_css": "Benutzerdefiniertes CSS", + "type_render_note": "Rendering-Notiz", + "type_web_view": "Webansicht", + "type_app_theme": "Benutzerdefiniertes Thema", + "toggle_tooltip_enable_tooltip": "Klicken, um diesen {{type}} zu aktivieren.", + "toggle_tooltip_disable_tooltip": "Klicken, um diesen {{type}} zu deaktivieren.", + "menu_docs": "Dokumentation öffnen", + "menu_execute_now": "Skript jetzt ausführen", + "menu_run": "Automatisch ausführen", + "menu_run_disabled": "Manuell", + "menu_run_backend_startup": "Wenn das Backend startet", + "menu_run_hourly": "Stündlich", + "menu_run_daily": "Täglich", + "menu_run_frontend_startup": "Wenn das Desktop-Frontend startet", + "menu_run_mobile_startup": "Wenn das mobile Frontend startet", + "menu_change_to_widget": "Zum Widget wechseln", + "menu_change_to_frontend_script": "Zum Frontend-Skript wechseln", + "menu_theme_base": "Themenbasis" + }, + "setup_form": { + "more_info": "Mehr erfahren" } } diff --git a/apps/client/src/translations/el/translation.json b/apps/client/src/translations/el/translation.json index cd1355575d..7512b9e705 100644 --- a/apps/client/src/translations/el/translation.json +++ b/apps/client/src/translations/el/translation.json @@ -13,6 +13,61 @@ "critical-error": { "title": "Κρίσιμο σφάλμα", "message": "Συνέβη κάποιο κρίσιμο σφάλμα, το οποίο δεν επιτρέπει στην εφαρμογή χρήστη να ξεκινήσει:\n\n{{message}}\n\nΤο πιθανότερο είναι να προκλήθηκε από κάποιο script που απέτυχε απρόοπτα. Δοκιμάστε να ξεκινήσετε την εφαρμογή σε ασφαλή λειτουργία για να λύσετε το πρόβλημα." - } + }, + "widget-error": { + "title": "Δεν ήταν δυνατή η αρχικοποίηση του widget", + "message-custom": "Προσαρμοσμένο widget της σημείωσης με ID \"{{id}}\", με τίτλο \"{{title}}\", δεν ήταν δυνατό να αρχικοποιηθεί λόγω:\n\n{{message}}", + "message-unknown": "Άγνωστο widget δεν ήταν δυνατό να αρχικοποιηθεί λόγω:\n\n{{message}}" + }, + "bundle-error": { + "title": "Δεν ήταν δυνατή η φόρτωση προσαρμοσμένου script", + "message": "Το script δεν ήταν δυνατό να εκτελεστεί λόγω:\n\n{{message}}" + }, + "widget-list-error": { + "title": "Δεν ήταν δυνατή η λήψη της λίστας των widgets από τον server" + }, + "widget-render-error": { + "title": "Δεν ήταν δυνατή η απόδοση προσαρμοσμένου React widget" + }, + "widget-missing-parent": "Το προσαρμοσμένο widget δεν έχει ορισμένη την υποχρεωτική ιδιότητα '{{property}}'.\n\nΕάν το script προορίζεται για εκτέλεση χωρίς UI element, χρησιμοποιήστε '#run=frontendStartup' αντί για αυτό.", + "open-script-note": "Άνοιγμα σημείωσης script", + "scripting-error": "Σφάλμα προσαρμοσμένου script: {{title}}" + }, + "bookmark_buttons": { + "bookmarks": "Σελιδοδείκτες" + }, + "add_link": { + "add_link": "Προσθήκη συνδέσμου", + "help_on_links": "Βοήθεια για συνδέσμους", + "note": "Σημείωση", + "search_note": "Αναζήτηση σημείωσης με βάση το όνομά της", + "link_title_mirrors": "Ο τίτλος του συνδέσμου αντικατοπτρίζει τον τρέχοντα τίτλο της σημείωσης", + "link_title_arbitrary": "Ο τίτλος του συνδέσμου μπορεί να τροποποιηθεί ελεύθερα", + "link_title": "Τίτλος συνδέσμου", + "button_add_link": "Προσθήκη συνδέσμου" + }, + "branch_prefix": { + "edit_branch_prefix": "Επεξεργασία προθέματος κλάδου", + "edit_branch_prefix_multiple": "Επεξεργασία προθέματος κλάδου για {{count}} κλάδους", + "help_on_tree_prefix": "Βοήθεια για πρόθεμα δέντρου", + "prefix": "Πρόθεμα: ", + "save": "Αποθήκευση", + "branch_prefix_saved": "Το πρόθεμα κλάδου αποθηκεύτηκε.", + "branch_prefix_saved_multiple": "Το πρόθεμα κλάδου αποθηκεύτηκε για {{count}} κλάδους.", + "affected_branches": "Επηρεαζόμενοι κλάδοι ({{count}}):" + }, + "bulk_actions": { + "bulk_actions": "Μαζικές ενέργειες", + "affected_notes": "Επηρεαζόμενες σημειώσεις", + "include_descendants": "Συμπερίληψη απογόνων των επιλεγμένων σημειώσεων", + "available_actions": "Διαθέσιμες ενέργειες", + "chosen_actions": "Επιλεγμένες ενέργειες", + "execute_bulk_actions": "Εκτέλεση μαζικών ενεργειών", + "bulk_actions_executed": "Οι μαζικές ενέργειες εκτελέστηκαν επιτυχώς.", + "none_yet": "Καμία ακόμη… προσθέστε μια ενέργεια επιλέγοντας μία από τις διαθέσιμες παραπάνω.", + "labels": "Ετικέτες", + "relations": "Συσχετίσεις", + "notes": "Σημειώσεις", + "other": "Λοιπά" } } diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index 6bd13a3346..377a287183 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -662,7 +662,8 @@ "show-cheatsheet": "Show Cheatsheet", "toggle-zen-mode": "Zen Mode", "new-version-available": "New Update Available", - "download-update": "Get Version {{latestVersion}}" + "download-update": "Get Version {{latestVersion}}", + "search_notes": "Search notes" }, "zen_mode": { "button_exit": "Exit Zen Mode" @@ -745,7 +746,7 @@ "button_title": "Export diagram as SVG" }, "relation_map_buttons": { - "create_child_note_title": "Create new child note and add it into this relation map", + "create_child_note_title": "Create child note and add it to map", "reset_pan_zoom_title": "Reset pan & zoom to initial coordinates and magnification", "zoom_in_title": "Zoom In", "zoom_out_title": "Zoom Out" @@ -760,7 +761,9 @@ "delete_this_note": "Delete this note", "note_revisions": "Note revisions", "error_cannot_get_branch_id": "Cannot get branchId for notePath '{{notePath}}'", - "error_unrecognized_command": "Unrecognized command {{command}}" + "error_unrecognized_command": "Unrecognized command {{command}}", + "backlinks": "Backlinks", + "content_language_switcher": "Content language: {{language}}" }, "note_icon": { "change_note_icon": "Change note icon", @@ -905,6 +908,7 @@ "debug": "debug", "debug_description": "Debug will print extra debugging information into the console to aid in debugging complex queries", "action": "action", + "option": "option", "search_button": "Search", "search_execute": "Search & Execute actions", "save_to_note": "Save to note", @@ -1006,7 +1010,7 @@ "no_attachments": "This note has no attachments." }, "book": { - "no_children_help": "This collection doesn't have any child notes so there's nothing to display. See wiki for details.", + "no_children_help": "This collection doesn't have any child notes so there's nothing to display.", "drag_locked_title": "Locked for editing", "drag_locked_message": "Dragging not allowed since the collection is locked for editing." }, @@ -1063,13 +1067,21 @@ "click_on_canvas_to_place_new_note": "Click on canvas to place new note" }, "render": { - "note_detail_render_help_1": "This help note is shown because this note of type Render HTML doesn't have required relation to function properly.", - "note_detail_render_help_2": "Render HTML note type is used for scripting. In short, you have a HTML code note (optionally with some JavaScript) and this note will render it. To make it work, you need to define a relation called \"renderNote\" pointing to the HTML note to render." + "setup_title": "Display custom HTML or Preact JSX inside this note", + "setup_create_sample_preact": "Create sample note with Preact", + "setup_create_sample_html": "Create sample note with HTML", + "setup_sample_created": "A sample note was created as a child note.", + "disabled_description": "This render notes comes from an external source. To protect you from malicious content, it is not enabled by default. Make sure you trust the source before enabling it.", + "disabled_button_enable": "Enable render note" }, - "web_view": { - "web_view": "Web View", - "embed_websites": "Note of type Web View allows you to embed websites into Trilium.", - "create_label": "To start, please create a label with a URL address you want to embed, e.g. #webViewSrc=\"https://www.google.com\"" + "web_view_setup": { + "title": "Create a live view of a webpage directly into Trilium", + "url_placeholder": "Enter or paste the website address, for example https://triliumnotes.org", + "create_button": "Create Web View", + "invalid_url_title": "Invalid address", + "invalid_url_message": "Insert a valid web address, for example https://triliumnotes.org.", + "disabled_description": "This web view was imported from an external source. To help protect you from phishing or malicious content, it isn’t loading automatically. You can enable it if you trust the source.", + "disabled_button_enable": "Enable web view" }, "backend_log": { "refresh": "Refresh" @@ -1585,7 +1597,8 @@ "description": "Description", "reload_app": "Reload app to apply changes", "set_all_to_default": "Set all shortcuts to the default", - "confirm_reset": "Do you really want to reset all keyboard shortcuts to the default?" + "confirm_reset": "Do you really want to reset all keyboard shortcuts to the default?", + "no_results": "No shortcuts found matching '{{filter}}'" }, "spellcheck": { "title": "Spell Check", @@ -1791,6 +1804,8 @@ "printing": "Printing in progress...", "printing_pdf": "Exporting to PDF in progress...", "print_report_title": "Print report", + "print_report_error_title": "Failed to print", + "print_report_stack_trace": "Stack trace", "print_report_collection_content_one": "{{count}} note in the collection could not be printed because they are not supported or they are protected.", "print_report_collection_content_other": "{{count}} notes in the collection could not be printed because they are not supported or they are protected.", "print_report_collection_details_button": "See details", @@ -2095,7 +2110,8 @@ "raster": "Raster", "vector_light": "Vector (Light)", "vector_dark": "Vector (Dark)", - "show-scale": "Show scale" + "show-scale": "Show scale", + "show-labels": "Show marker names" }, "table_context_menu": { "delete_row": "Delete row" @@ -2174,8 +2190,9 @@ "percentage": "%" }, "pagination": { - "page_title": "Page of {{startIndex}} - {{endIndex}}", - "total_notes": "{{count}} notes" + "total_notes": "{{count}} notes", + "prev_page": "Previous page", + "next_page": "Next page" }, "collections": { "rendering_error": "Unable to show content due to an error." @@ -2276,5 +2293,35 @@ "title_one": "{{count}} tab", "title_other": "{{count}} tabs", "more_options": "More options" + }, + "bookmark_buttons": { + "bookmarks": "Bookmarks" + }, + "active_content_badges": { + "type_icon_pack": "Icon pack", + "type_backend_script": "Backend script", + "type_frontend_script": "Frontend script", + "type_widget": "Widget", + "type_app_css": "Custom CSS", + "type_render_note": "Render note", + "type_web_view": "Web view", + "type_app_theme": "Custom theme", + "toggle_tooltip_enable_tooltip": "Click to enable this {{type}}.", + "toggle_tooltip_disable_tooltip": "Click to disable this {{type}}.", + "menu_docs": "Open documentation", + "menu_execute_now": "Execute script now", + "menu_run": "Run automatically", + "menu_run_disabled": "Manually", + "menu_run_backend_startup": "When the backend starts up", + "menu_run_hourly": "Hourly", + "menu_run_daily": "Daily", + "menu_run_frontend_startup": "When the desktop frontend starts up", + "menu_run_mobile_startup": "When the mobile frontend starts up", + "menu_change_to_widget": "Change to widget", + "menu_change_to_frontend_script": "Change to frontend script", + "menu_theme_base": "Theme base" + }, + "setup_form": { + "more_info": "Learn more" } } diff --git a/apps/client/src/translations/es/translation.json b/apps/client/src/translations/es/translation.json index 896a8f62be..a583bc2b0d 100644 --- a/apps/client/src/translations/es/translation.json +++ b/apps/client/src/translations/es/translation.json @@ -662,13 +662,14 @@ "show-cheatsheet": "Mostrar hoja de trucos", "toggle-zen-mode": "Modo Zen", "new-version-available": "Nueva actualización disponible", - "download-update": "Obtener versión {{latestVersion}}" + "download-update": "Obtener versión {{latestVersion}}", + "search_notes": "Buscar notas" }, "zen_mode": { "button_exit": "Salir del modo Zen" }, "sync_status": { - "unknown": "

El estado de sincronización será conocido una vez que el siguiente intento de sincronización comience.

Dé clic para activar la sincronización ahora

", + "unknown": "

El estado de sincronización será conocido una vez que el siguiente intento de sincronización comience.

Dé clic para activar la sincronización ahora.

", "connected_with_changes": "

Conectado al servidor de sincronización.
Hay cambios pendientes que aún no se han sincronizado.

Dé clic para activar la sincronización.

", "connected_no_changes": "

Conectado al servidor de sincronización.
Todos los cambios ya han sido sincronizados.

Dé clic para activar la sincronización.

", "disconnected_with_changes": "

El establecimiento de la conexión con el servidor de sincronización no ha tenido éxito.
Hay algunos cambios pendientes que aún no se han sincronizado.

Dé clic para activar la sincronización.

", @@ -745,7 +746,7 @@ "button_title": "Exportar diagrama como SVG" }, "relation_map_buttons": { - "create_child_note_title": "Crear una nueva subnota y agregarla a este mapa de relaciones", + "create_child_note_title": "Crear una subnota y agregarla al mapa", "reset_pan_zoom_title": "Restablecer la panorámica y el zoom a las coordenadas y ampliación iniciales", "zoom_in_title": "Acercar", "zoom_out_title": "Alejar" @@ -754,14 +755,16 @@ "relation": "relación", "backlink_one": "{{count}} Vínculo de retroceso", "backlink_many": "{{count}} Vínculos de retroceso", - "backlink_other": "{{count}} vínculos de retroceso" + "backlink_other": "{{count}} Vínculos de retroceso" }, "mobile_detail_menu": { "insert_child_note": "Insertar subnota", "delete_this_note": "Eliminar esta nota", - "error_cannot_get_branch_id": "No se puede obtener el branchID del notePath '{{notePath}}'", + "error_cannot_get_branch_id": "No se puede obtener el branchId del notePath '{{notePath}}'", "error_unrecognized_command": "Comando no reconocido {{command}}", - "note_revisions": "Revisiones de notas" + "note_revisions": "Revisiones de notas", + "backlinks": "Vínculos de retroceso", + "content_language_switcher": "Idioma de contenido: {{language}}" }, "note_icon": { "change_note_icon": "Cambiar icono de nota", @@ -914,7 +917,8 @@ "unknown_search_option": "Opción de búsqueda desconocida {{searchOptionName}}", "search_note_saved": "La nota de búsqueda se ha guardado en {{- notePathTitle}}", "actions_executed": "Las acciones han sido ejecutadas.", - "view_options": "Ver opciones:" + "view_options": "Ver opciones:", + "option": "opción" }, "similar_notes": { "title": "Notas similares", @@ -1008,7 +1012,7 @@ "no_attachments": "Esta nota no tiene archivos adjuntos." }, "book": { - "no_children_help": "Esta nota de tipo libro no tiene ninguna subnota así que no hay nada que mostrar. Véa la wiki para más detalles.", + "no_children_help": "Esta colección no tiene ninguna subnota así que no hay nada que mostrar.", "drag_locked_title": "Bloqueado para edición", "drag_locked_message": "No se permite Arrastrar pues la colección está bloqueada para edición." }, @@ -1064,15 +1068,6 @@ "default_new_note_title": "nueva nota", "click_on_canvas_to_place_new_note": "Haga clic en el lienzo para colocar una nueva nota" }, - "render": { - "note_detail_render_help_1": "Esta nota de ayuda se muestra porque esta nota de tipo Renderizar HTML no tiene la relación requerida para funcionar correctamente.", - "note_detail_render_help_2": "El tipo de nota Render HTML es usado para scripting. De forma resumida, tiene una nota con código HTML (opcionalmente con algo de JavaScript) y esta nota la renderizará. Para que funcione, es necesario definir una relación llamada \"renderNote\" apuntando a la nota HTML nota a renderizar." - }, - "web_view": { - "web_view": "Vista web", - "embed_websites": "La nota de tipo Web View le permite insertar sitios web en Trilium.", - "create_label": "Para comenzar, por favor cree una etiqueta con una dirección URL que desee empotrar, e.g. #webViewSrc=\"https://www.google.com\"" - }, "backend_log": { "refresh": "Refrescar" }, @@ -1565,7 +1560,7 @@ "shortcuts": { "keyboard_shortcuts": "Atajos de teclado", "multiple_shortcuts": "Varios atajos para la misma acción se pueden separar mediante comas.", - "electron_documentation": "Véa la documentación de Electron para los modificadores y códigos de tecla disponibles.", + "electron_documentation": "Consulte la documentación de Electron para los modificadores y códigos de tecla disponibles.", "type_text_to_filter": "Escriba texto para filtrar los accesos directos...", "action_name": "Nombre de la acción", "shortcuts": "Atajos", @@ -1573,7 +1568,8 @@ "description": "Descripción", "reload_app": "Vuelva a cargar la aplicación para aplicar los cambios", "set_all_to_default": "Establecer todos los accesos directos al valor predeterminado", - "confirm_reset": "¿Realmente desea restablecer todos los atajos de teclado a sus valores predeterminados?" + "confirm_reset": "¿Realmente desea restablecer todos los atajos de teclado a sus valores predeterminados?", + "no_results": "No se encontraron atajos que coincidan con '{{filter}} '" }, "spellcheck": { "title": "Revisión ortográfica", @@ -1780,7 +1776,9 @@ "print_report_collection_content_other": "{{count}} notas en la colección no se pueden imprimir porque no son compatibles o están protegidas.", "print_report_title": "Imprimir informe", "print_report_collection_details_button": "Ver detalles", - "print_report_collection_details_ignored_notes": "Notas ignoradas" + "print_report_collection_details_ignored_notes": "Notas ignoradas", + "print_report_stack_trace": "Rastreo de pila", + "print_report_error_title": "Fallo al imprimir" }, "note_title": { "placeholder": "escriba el título de la nota aquí...", @@ -1828,7 +1826,7 @@ "no_headings": "Sin encabezados." }, "watched_file_update_status": { - "file_last_modified": "Archivo ha sido modificado por última vez en.", + "file_last_modified": "El archivo ha sido modificado por última vez en .", "upload_modified_file": "Subir archivo modificado", "ignore_this_change": "Ignorar este cambio" }, @@ -2052,7 +2050,8 @@ "max-nesting-depth": "Máxima profundidad de anidamiento:", "vector_light": "Vector (claro)", "vector_dark": "Vector (oscuro)", - "raster": "Trama" + "raster": "Trama", + "show-labels": "Mostrar nombres de marcadores" }, "table_context_menu": { "delete_row": "Eliminar fila" @@ -2161,7 +2160,8 @@ }, "pagination": { "total_notes": "{{count}} notas", - "page_title": "Página de {{startIndex}} - {{endIndex}}" + "prev_page": "Página anterior", + "next_page": "Página siguiente" }, "presentation_view": { "edit-slide": "Editar este slide", @@ -2285,5 +2285,58 @@ }, "platform_indicator": { "available_on": "Disponible en {{platform}}" + }, + "mobile_tab_switcher": { + "title_one": "{{count}} pestaña", + "title_many": "{{count}} pestañas", + "title_other": "{{count}} pestañas", + "more_options": "Más opciones" + }, + "bookmark_buttons": { + "bookmarks": "Marcadores" + }, + "web_view_setup": { + "title": "Crear una vista en vivo de una página web directamente en Trilium", + "url_placeholder": "Ingresar o pegar la dirección del sitio web, por ejemplo https://triliumnotes.org", + "create_button": "Crear Vista Web", + "invalid_url_title": "Dirección inválida", + "invalid_url_message": "Ingrese una dirección web válida, por ejemplo https://triliumnotes.org.", + "disabled_description": "Esta vista web fue importada de una fuente externa. Para ayudarlo a protegerse del phishing o el contenido malicioso, no se está cargando automáticamente. Puede activarlo si confía en la fuente.", + "disabled_button_enable": "Habilita vista web" + }, + "render": { + "setup_title": "Mostrar HTML personalizado o Preact JSX dentro de esta nota", + "setup_create_sample_preact": "Crear nota de muestra con Preact", + "setup_create_sample_html": "Crear nota de muestra con HTML", + "setup_sample_created": "Se creó una nota de muestra como subnota.", + "disabled_description": "Esta nota de renderización proviene de una fuente externa. Para protegerlo de contenido malicioso, no está habilitado por defecto. Asegúrese de confiar en la fuente antes de habilitarla.", + "disabled_button_enable": "Habilitar nota de renderización" + }, + "active_content_badges": { + "type_icon_pack": "Paquete de iconos", + "type_backend_script": "Script de backend", + "type_frontend_script": "Script de frontend", + "type_widget": "Widget", + "type_app_css": "CSS personalizado", + "type_render_note": "Nota de renderización", + "type_web_view": "Vista web", + "type_app_theme": "Tema personalizado", + "toggle_tooltip_enable_tooltip": "Haga clic para habilitar este {{type}}.", + "toggle_tooltip_disable_tooltip": "Haga clic para deshabilitar este {{type}}.", + "menu_docs": "Abrir documentación", + "menu_execute_now": "Ejecutar script ahora", + "menu_run": "Ejecutar automáticamente", + "menu_run_disabled": "Manualmente", + "menu_run_backend_startup": "Cuando el backend inicia", + "menu_run_hourly": "Cada hora", + "menu_run_daily": "Diariamente", + "menu_run_frontend_startup": "Cuando el frontend de escritorio inicia", + "menu_run_mobile_startup": "Cuando el frontend móvil inicia", + "menu_change_to_widget": "Cambiar a widget", + "menu_change_to_frontend_script": "Cambiar a script de frontend", + "menu_theme_base": "Tema base" + }, + "setup_form": { + "more_info": "Para saber más" } } diff --git a/apps/client/src/translations/fr/translation.json b/apps/client/src/translations/fr/translation.json index 2900c5de56..69b4eee16a 100644 --- a/apps/client/src/translations/fr/translation.json +++ b/apps/client/src/translations/fr/translation.json @@ -1053,15 +1053,6 @@ "default_new_note_title": "nouvelle note", "click_on_canvas_to_place_new_note": "Cliquez sur le canevas pour placer une nouvelle note" }, - "render": { - "note_detail_render_help_1": "Cette note d'aide s'affiche car cette note de type Rendu HTML n'a pas la relation requise pour fonctionner correctement.", - "note_detail_render_help_2": "Le type de note Rendu HTML est utilisé pour les scripts. En résumé, vous disposez d'une note de code HTML (éventuellement contenant JavaScript) et cette note affichera le rendu. Pour que cela fonctionne, vous devez définir une relation appelée \"renderNote\" pointant vers la note HTML à rendre." - }, - "web_view": { - "web_view": "Affichage Web", - "embed_websites": "Les notes de type Affichage Web vous permet d'intégrer des sites Web dans Trilium.", - "create_label": "Pour commencer, veuillez créer un label avec l'adresse URL que vous souhaitez intégrer, par ex. #webViewSrc=\"https://www.google.com\"" - }, "backend_log": { "refresh": "Rafraîchir" }, @@ -2058,7 +2049,6 @@ "percentage": "%" }, "pagination": { - "page_title": "Page de {{startIndex}} - {{endIndex}}", "total_notes": "{{count}} notes" }, "collections": { diff --git a/apps/client/src/translations/ga/translation.json b/apps/client/src/translations/ga/translation.json new file mode 100644 index 0000000000..5592c8f3a9 --- /dev/null +++ b/apps/client/src/translations/ga/translation.json @@ -0,0 +1,2372 @@ +{ + "global_menu": { + "about": "Maidir le Trilium Notes", + "menu": "Roghchlár", + "options": "Roghanna", + "open_new_window": "Oscail Fuinneog Nua", + "switch_to_mobile_version": "Athraigh go Leagan Soghluaiste", + "switch_to_desktop_version": "Athraigh go Leagan Deisce", + "zoom": "Zúmáil", + "toggle_fullscreen": "Lánscáileán a Athsholáthar", + "zoom_out": "Zúmáil Amach", + "reset_zoom_level": "Athshocraigh Leibhéal Súmála", + "zoom_in": "Zúmáil Isteach", + "configure_launchbar": "Cumraigh an Barra Seoladh", + "show_shared_notes_subtree": "Taispeáin Fo-chrann Nótaí Comhroinnte", + "advanced": "Ardleibhéil", + "open_dev_tools": "Oscail Uirlisí Forbróra", + "open_sql_console": "Oscail Consól SQL", + "open_sql_console_history": "Oscail Stair Chonsól SQL", + "open_search_history": "Oscail Stair Chuardaigh", + "show_backend_log": "Taispeáin Logáil an Chúil", + "reload_hint": "Is féidir le hathlódáil cabhrú le roinnt fabhtanna amhairc gan an aip ar fad a atosú.", + "reload_frontend": "Athlódáil an Tosaigh", + "show_hidden_subtree": "Taispeáin Fo-chrann Folaithe", + "show_help": "Taispeáin Cabhair", + "logout": "Logáil Amach", + "show-cheatsheet": "Taispeáin Bileog leideanna", + "toggle-zen-mode": "Mód Zen", + "new-version-available": "Nuashonrú Nua ar Fáil", + "download-update": "Faigh Leagan {{latestVersion}}", + "search_notes": "Cuardaigh nótaí" + }, + "about": { + "title": "Maidir le Trilium Notes", + "homepage": "Leathanach baile:", + "app_version": "Leagan an aip:", + "db_version": "Leagan DB:", + "sync_version": "Leagan sioncrónaithe:", + "build_date": "Dáta tógála:", + "build_revision": "Athbhreithniú tógála:", + "data_directory": "Eolaire sonraí:" + }, + "toast": { + "critical-error": { + "title": "Earráid chriticiúil", + "message": "Tharla earráid chriticiúil a chuireann cosc ar an bhfeidhmchlár cliant tosú:\n\n{{message}}\n\nIs dóichí gur teip gan choinne ar script is cúis leis seo. Bain triail as an bhfeidhmchlár a thosú i mód sábháilte agus an fhadhb a réiteach." + }, + "widget-error": { + "title": "Theip ar ghiuirléid a thosú", + "message-custom": "Níorbh fhéidir giuirléid saincheaptha ó nóta leis an ID \"{{id}}\", dar teideal \"{{title}}\" a thosú mar gheall ar:\n\n{{message}}", + "message-unknown": "Níorbh fhéidir giuirléid anaithnid a thosú mar gheall ar:\n\n{{message}}" + }, + "bundle-error": { + "title": "Theip ar script saincheaptha a luchtú", + "message": "Níorbh fhéidir an script a fhorghníomhú mar gheall ar:\n\n{{message}}" + }, + "widget-list-error": { + "title": "Theip ar an liosta giuirléidí a fháil ón bhfreastalaí" + }, + "widget-render-error": { + "title": "Theip ar ghiuirléid React saincheaptha a rindreáil" + }, + "widget-missing-parent": "Níl an mhaoin éigeantach '{{property}}' sainmhínithe ag an ngiuirléid saincheaptha.\n\nMás é an aidhm atá leis an script seo a rith gan eilimint Chomhéadain Úsáideora, bain úsáid as '#run=frontendStartup' ina ionad.", + "open-script-note": "Nóta scripte oscailte", + "scripting-error": "Earráid scripte saincheaptha: {{title}}" + }, + "add_link": { + "add_link": "Cuir nasc leis", + "help_on_links": "Cabhair le naisc", + "note": "Nóta", + "search_note": "cuardach nóta de réir a ainm", + "link_title_mirrors": "Léiríonn teideal an naisc teideal reatha an nóta", + "link_title_arbitrary": "is féidir teideal an naisc a athrú go treallach", + "link_title": "Teideal an naisc", + "button_add_link": "Cuir nasc leis" + }, + "branch_prefix": { + "edit_branch_prefix": "Cuir réimír na brainse in eagar", + "edit_branch_prefix_multiple": "Cuir réimír brainse in eagar do bhrainse {{count}}", + "help_on_tree_prefix": "Cabhair maidir le réimír Crann", + "prefix": "Réimír: ", + "save": "Sábháil", + "branch_prefix_saved": "Tá réimír na brainse sábháilte.", + "branch_prefix_saved_multiple": "Tá réimír brainse sábháilte do {{count}} brainse.", + "affected_branches": "Brainsí atá buailte ({{count}}):" + }, + "bulk_actions": { + "bulk_actions": "Gníomhartha mórchóir", + "affected_notes": "Nótaí a ndearnadh difear dóibh", + "include_descendants": "Cuir sliocht na nótaí roghnaithe san áireamh", + "available_actions": "Gníomhartha atá ar fáil", + "chosen_actions": "Gníomhartha roghnaithe", + "execute_bulk_actions": "Gníomhartha mórchóir a fhorghníomhú", + "bulk_actions_executed": "Tá gníomhartha mórchóir curtha i gcrích go rathúil.", + "none_yet": "Gan aon cheann fós... cuir gníomh leis trí chliceáil ar cheann de na cinn atá ar fáil thuas.", + "labels": "Lipéid", + "relations": "Caidreamh", + "notes": "Nótaí", + "other": "Eile" + }, + "clone_to": { + "clone_notes_to": "Nótaí clónála chuig...", + "help_on_links": "Cabhair le naisc", + "notes_to_clone": "Nótaí le clónáil", + "target_parent_note": "Nóta tuismitheora spriocdhírithe", + "search_for_note_by_its_name": "cuardach nóta de réir a ainm", + "cloned_note_prefix_title": "Taispeánfar nóta clónáilte sa chrann nótaí leis an réimír tugtha", + "prefix_optional": "Réimír (roghnach)", + "clone_to_selected_note": "Clónáil chuig an nóta roghnaithe", + "no_path_to_clone_to": "Gan aon chonair le clónáil chuige.", + "note_cloned": "Tabhair faoi deara gur clónáladh \"{{clonedTitle}}\" isteach i \"{{targetTitle}}\"" + }, + "confirm": { + "confirmation": "Deimhniú", + "cancel": "Cealaigh", + "ok": "Ceart go leor", + "are_you_sure_remove_note": "An bhfuil tú cinnte gur mian leat an nóta \"{{title}}\" a bhaint den léarscáil caidrimh? ", + "if_you_dont_check": "Mura seiceálann tú é seo, ní bhainfear an nóta ach den léarscáil chaidrimh.", + "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.", + "erase_notes_warning": "Scrios nótaí go buan (ní féidir é seo a chealú), lena n-áirítear na clónanna go léir. Cuirfidh sé seo iallach ar an bhfeidhmchlár athlódáil.", + "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}}." + }, + "export": { + "export_note_title": "Nóta easpórtála", + "close": "Dún", + "export_type_subtree": "An nóta seo agus a shliocht uile", + "format_html": "HTML - molta mar go gcoinníonn sé an fhormáid go léir", + "format_html_zip": "HTML i gcartlann ZIP - moltar é seo ós rud é go gcoimeádann sé seo an fhormáidiú go léir.", + "format_markdown": "Markdown - caomhnaíonn sé seo an chuid is mó den fhormáidiú.", + "format_opml": "OPML - formáid idirmhalartaithe imlíneach le haghaidh téacs amháin. Níl formáidiú, íomhánna agus comhaid san áireamh.", + "opml_version_1": "OPML v1.0 - téacs simplí amháin", + "opml_version_2": "OPML v2.0 - ceadaíonn HTML freisin", + "export_type_single": "An nóta seo amháin gan a shliocht", + "export": "Easpórtáil", + "choose_export_type": "Roghnaigh cineál onnmhairithe ar dtús le do thoil", + "export_status": "Stádas onnmhairithe", + "export_in_progress": "Easpórtáil ar siúl: {{progressCount}}", + "export_finished_successfully": "Críochnaíodh an easpórtáil go rathúil.", + "format_pdf": "PDF - le haghaidh priontála nó comhroinnte.", + "share-format": "HTML le haghaidh foilsitheoireachta gréasáin - úsáideann sé an téama céanna a úsáidtear le haghaidh nótaí comhroinnte, ach is féidir é a fhoilsiú mar shuíomh gréasáin statach." + }, + "help": { + "title": "Bileog leideanna", + "editShortcuts": "Cuir aicearraí méarchláir in eagar", + "noteNavigation": "Nascleanúint nótaí", + "goUpDown": "téigh suas/síos sa liosta nótaí", + "collapseExpand": "nód a chomhdhlúthú/a leathnú", + "notSet": "gan socrú", + "goBackForwards": "dul ar ais/ar aghaidh sa stair", + "showJumpToNoteDialog": "taispeáin an dialóg \"Léim go\"", + "scrollToActiveNote": "scrollaigh go dtí an nóta gníomhach", + "jumpToParentNote": "léim go dtí an nóta tuismitheora", + "collapseWholeTree": "crann nótaí iomlán a fhilleadh", + "collapseSubTree": "fo-chrann a chomhdhlúthú", + "tabShortcuts": "Aicearraí cluaisíní", + "newTabNoteLink": "ar nasc nóta osclaíonn nóta i gcluaisín nua", + "newTabWithActivationNoteLink": "osclaítear an nasc ar nóta agus gníomhaíonn sé an nóta i gcluaisín nua", + "onlyInDesktop": "I ríomhairí deisce amháin (tógáil Electron)", + "openEmptyTab": "oscail cluaisín folamh", + "closeActiveTab": "dún an cluaisín gníomhach", + "activateNextTab": "gníomhachtaigh an chéad chluaisín eile", + "activatePreviousTab": "gníomhachtaigh an cluaisín roimhe seo", + "creatingNotes": "Nótaí á gcruthú", + "createNoteAfter": "cruthaigh nóta nua i ndiaidh an nóta ghníomhaigh", + "createNoteInto": "cruthaigh fo-nóta nua i nóta gníomhach", + "editBranchPrefix": "cuir réimír in eagar den chlón nóta gníomhach", + "movingCloningNotes": "Nótaí a bhogadh / a chlónáil", + "moveNoteUpDown": "bog nóta suas/síos sa liosta nótaí", + "moveNoteUpHierarchy": "bog nóta suas san ordlathas", + "multiSelectNote": "nóta ilroghnaithe thuas/thíos", + "selectAllNotes": "roghnaigh na nótaí go léir sa leibhéal reatha", + "selectNote": "roghnaigh nóta", + "copyNotes": "cóipeáil an nóta gníomhach (nó an rogha reatha) isteach sa ghearrthaisce (a úsáidtear le haghaidh clónála)", + "cutNotes": "gearr an nóta reatha (nó an rogha reatha) isteach sa ghearrthaisce (a úsáidtear chun nótaí a bhogadh)", + "pasteNotes": "greamaigh nóta(í) mar fho-nóta isteach sa nóta gníomhach (is é sin bogadh nó clónáil ag brath ar an cóipeáladh nó ar gearradh isteach sa ghearrthaisce é)", + "deleteNotes": "scrios nóta / fo-chrann", + "editingNotes": "Nótaí á n-eagarthóireacht", + "editNoteTitle": "Sa phána crainn, aistreofar ón bpána crainn go teideal an nóta. Má iontráiltear ó theideal an nóta, aistreofar an fócas go dtí an t-eagarthóir téacs. Aistreofar Ctrl+. ar ais ón eagarthóir go dtí an phána crainn.", + "createEditLink": "cruthaigh / cuir in eagar nasc seachtrach", + "createInternalLink": "nasc inmheánach a chruthú", + "followLink": "lean an nasc faoin gcúrsóir", + "insertDateTime": "cuir isteach an dáta agus an t-am reatha ag suíomh an charet", + "jumpToTreePane": "léim ar shiúl go dtí an painéal crainn agus scrollaigh go dtí an nóta gníomhach", + "markdownAutoformat": "Uathfhormáidiú cosúil le Markdown", + "headings": "##, ###, #### etc. agus spás ina dhiaidh sin do cheannteidil", + "bulletList": "*- agus spás ina dhiaidh sin le haghaidh liosta urchair", + "numberedList": "1.1) agus spás ina dhiaidh sin le haghaidh liosta uimhrithe", + "blockQuote": "tosaigh líne le > agus ina dhiaidh sin spás le haghaidh athfhriotail bhloc", + "troubleshooting": "Fabhtcheartú", + "reloadFrontend": "athlódáil tosaigh Trilium", + "showDevTools": "taispeáin uirlisí forbróra", + "showSQLConsole": "taispeáin consól SQL", + "other": "Eile", + "quickSearch": "díriú ar ionchur cuardaigh thapa", + "inPageSearch": "cuardach in-leathanaigh" + }, + "import": { + "importIntoNote": "Iompórtáil isteach i nóta", + "chooseImportFile": "Roghnaigh comhad allmhairithe", + "importDescription": "Déanfar ábhar an chomhaid/na gcomhad roghnaithe a allmhairiú mar nóta/nótaí linbh isteach", + "importZipRecommendation": "Agus comhad ZIP á iompórtáil, léireoidh ordlathas na nótaí struchtúr an fho-eolaire laistigh den chartlann.", + "options": "Roghanna", + "safeImportTooltip": "Is féidir go mbeadh scripteanna inrite a d'fhéadfadh iompar díobhálach a bheith iontu i gcomhaid easpórtála Trilium .zip. Díghníomhachtóidh allmhairiú sábháilte forghníomhú uathoibríoch na scripteanna allmhairithe go léir. Díthiceáil \"Allmhairiú sábháilte\" ach amháin má tá sé i gceist go mbeadh scripteanna inrite sa chartlann allmhairithe agus má tá muinín iomlán agat as ábhar an chomhaid allmhairithe.", + "safeImport": "Allmhairiú sábháilte", + "explodeArchivesTooltip": "Má tá tic sa bhosca seo léifidh Trilium comhaid .zip, .enex agus .opml agus cruthóidh sé nótaí ó chomhaid laistigh de na cartlanna sin. Mura bhfuil an tic sa bhosca seo, ceanglóidh Trilium na cartlanna féin leis an nóta.", + "explodeArchives": "Léigh ábhar na gcartlann .zip, .enex agus .opml.", + "shrinkImagesTooltip": "

Má roghnaíonn tú an rogha seo, déanfaidh Trilium iarracht na híomhánna allmhairithe a chrapadh trí scálú agus uasmhéadú a d'fhéadfadh difear a dhéanamh don cháilíocht íomhá a bhraitear. Mura roghnaítear é, allmhaireofar íomhánna gan athruithe.

Ní bhaineann sé seo le hallmhairí .zip le meiteashonraí ós rud é go nglactar leis go bhfuil na comhaid seo uasmhéadaithe cheana féin.

", + "shrinkImages": "Laghdaigh íomhánna", + "textImportedAsText": "Iompórtáil HTML, Markdown agus TXT mar nótaí téacs mura bhfuil sé soiléir ó na meiteashonraí", + "codeImportedAsCode": "Iompórtáil comhaid chód aitheanta (m.sh. .json) mar nótaí cóid mura bhfuil sé soiléir ó na meiteashonraí", + "replaceUnderscoresWithSpaces": "Cuir spásanna in ionad fo-línte in ainmneacha nótaí allmhairithe", + "import": "Iompórtáil", + "failed": "Theip ar an allmhairiú: {{message}}.", + "html_import_tags": { + "title": "Clibeanna Iompórtála HTML", + "description": "Cumraigh cé na clibeanna HTML ba chóir a chaomhnú agus nótaí á n-allmhairiú. Bainfear clibeanna nach bhfuil sa liosta seo le linn allmhairithe. Baintear roinnt clibeanna (cosúil le 'script') i gcónaí ar mhaithe le slándáil.", + "placeholder": "Cuir isteach clibeanna HTML, ceann amháin in aghaidh na líne", + "reset_button": "Athshocraigh go dtí an Liosta Réamhshocraithe" + }, + "import-status": "Stádas allmhairithe", + "in-progress": "Iompórtáil ar siúl: {{progress}}", + "successful": "Críochnaíodh an t-allmhairiú go rathúil." + }, + "include_note": { + "dialog_title": "Cuir nóta san áireamh", + "label_note": "Nóta", + "placeholder_search": "cuardach nóta de réir a ainm", + "box_size_prompt": "Méid an bhosca den nóta atá san áireamh:", + "box_size_small": "beag (~ 10 líne)", + "box_size_medium": "meánach (~ 30 líne)", + "box_size_full": "lán (taispeánann an bosca an téacs iomlán)", + "button_include": "Cuir nóta san áireamh" + }, + "info": { + "modalTitle": "Teachtaireacht eolais", + "closeButton": "Dún", + "okButton": "Ceart go leor", + "copy_to_clipboard": "Cóipeáil chuig an ghearrthaisce" + }, + "jump_to_note": { + "search_placeholder": "Cuardaigh nóta de réir a ainm nó a chineáil > le haghaidh orduithe...", + "search_button": "Cuardaigh sa téacs iomlán" + }, + "markdown_import": { + "dialog_title": "Allmhairiú marcála síos", + "modal_body_text": "Mar gheall ar bhosca gainimh an bhrabhsálaí ní féidir an ghearrthaisce a léamh go díreach ó JavaScript. Greamaigh an Markdown le hiompórtáil chuig an limistéar téacs thíos agus cliceáil ar an gcnaipe Iompórtáil", + "import_button": "Iompórtáil", + "import_success": "Tá ábhar marcála síos allmhairithe isteach sa doiciméad." + }, + "move_to": { + "dialog_title": "Bog nótaí chuig ...", + "notes_to_move": "Nótaí le bogadh", + "target_parent_note": "Nóta tuismitheora spriocdhírithe", + "search_placeholder": "cuardach nóta de réir a ainm", + "move_button": "Bog go dtí an nóta roghnaithe", + "error_no_path": "Gan aon chosán le bogadh chuige.", + "move_success_message": "Tá nótaí roghnaithe bogtha isteach " + }, + "note_type_chooser": { + "change_path_prompt": "Athraigh cá háit le nóta nua a chruthú:", + "search_placeholder": "cuardaigh cosán de réir ainm (réamhshocraithe má tá sé folamh)", + "modal_title": "Roghnaigh cineál nóta", + "modal_body": "Roghnaigh cineál nóta / teimpléad don nóta nua:", + "templates": "Teimpléid", + "builtin_templates": "Teimpléid Tógtha isteach" + }, + "password_not_set": { + "title": "Níl an focal faire socraithe", + "body1": "Déantar nótaí faoi chosaint a chriptiú ag baint úsáide as pasfhocal úsáideora, ach níl an pasfhocal socraithe fós.", + "body2": "Chun nótaí a chosaint, cliceáil an cnaipe thíos chun an dialóg Roghanna a oscailt agus do phasfhocal a shocrú.", + "go_to_password_options": "Téigh go dtí roghanna Pasfhocal" + }, + "prompt": { + "title": "Spreag", + "ok": "Ceart go leor", + "defaultTitle": "Spreag" + }, + "protected_session_password": { + "modal_title": "Seisiún faoi chosaint", + "help_title": "Cabhair maidir le nótaí faoi chosaint", + "close_label": "Dún", + "form_label": "Chun dul ar aghaidh leis an ngníomh iarrtha ní mór duit seisiún faoi chosaint a thosú trí phasfhocal a iontráil:", + "start_button": "Tosaigh seisiún faoi chosaint" + }, + "recent_changes": { + "title": "Athruithe le déanaí", + "erase_notes_button": "Scrios nótaí scriosta anois", + "deleted_notes_message": "Tá nótaí scriosta scriosta.", + "no_changes_message": "Gan aon athruithe fós...", + "undelete_link": "díscriosadh", + "confirm_undelete": "Ar mhaith leat an nóta seo agus a fho-nótaí a athscriosadh?" + }, + "revisions": { + "note_revisions": "Athbhreithnithe Nótaí", + "delete_all_revisions": "Scrios gach athbhreithniú ar an nóta seo", + "delete_all_button": "Scrios gach athbhreithniú", + "help_title": "Cabhair le hathbhreithnithe nótaí", + "confirm_delete_all": "Ar mhaith leat gach athbhreithniú ar an nóta seo a scriosadh?", + "no_revisions": "Gan aon athbhreithnithe don nóta seo go fóill...", + "restore_button": "Athchóirigh", + "diff_on": "Taispeáin an difríocht", + "diff_off": "Taispeáin ábhar", + "diff_on_hint": "Cliceáil chun difríocht foinse an nóta a thaispeáint", + "diff_off_hint": "Cliceáil chun ábhar an nóta a thaispeáint", + "diff_not_available": "Níl an difríocht ar fáil.", + "confirm_restore": "Ar mhaith leat an t-athbhreithniú seo a athbhunú? Scríobhfaidh sé seo teideal agus ábhar reatha an nóta leis an athbhreithniú seo.", + "delete_button": "Delete", + "confirm_delete": "Ar mhaith leat an t-athbhreithniú seo a scriosadh?", + "revisions_deleted": "Scriosadh athbhreithnithe nótaí.", + "revision_restored": "Tá athbhreithniú an nóta athchóirithe.", + "revision_deleted": "Scriosadh athbhreithniú an nóta.", + "snapshot_interval": "Eatramh Léirmheasa ar Nóta: {{seconds}}s.", + "maximum_revisions": "Teorainn maidir le hathbhreithniú nóta: {{number}}.", + "settings": "Socruithe Athbhreithnithe Nóta", + "download_button": "Íoslódáil", + "mime": "MIME: ", + "file_size": "Méid comhaid:", + "preview_not_available": "Níl réamhamharc ar fáil don chineál nóta seo." + }, + "sort_child_notes": { + "sort_children_by": "Sórtáil páistí de réir...", + "sorting_criteria": "Critéir sórtála", + "title": "teideal", + "date_created": "dáta cruthaithe", + "date_modified": "dáta modhnaithe", + "sorting_direction": "Treo sórtála", + "ascending": "ag dul suas", + "descending": "ag dul síos", + "folders": "Fillteáin", + "sort_folders_at_top": "sórtáil fillteáin ag an mbarr", + "natural_sort": "Sórtáil Nádúrtha", + "sort_with_respect_to_different_character_sorting": "sórtáil i ndáil le rialacha éagsúla sórtála agus cóimheasa carachtar i dteangacha nó i réigiúin éagsúla.", + "natural_sort_language": "Teanga sórtála nádúrtha", + "the_language_code_for_natural_sort": "An cód teanga le haghaidh sórtáil nádúrtha, e.g. \"zh-CN\" don tSínis.", + "sort": "Sórtáil" + }, + "upload_attachments": { + "upload_attachments_to_note": "Uaslódáil ceangaltáin chuig nóta", + "choose_files": "Roghnaigh comhaid", + "files_will_be_uploaded": "Uaslódálfar comhaid mar cheangaltáin isteach i {{noteTitle}}", + "options": "Roghanna", + "shrink_images": "Laghdaigh íomhánna", + "upload": "Uaslódáil", + "tooltip": "Má roghnaíonn tú an rogha seo, déanfaidh Trilium iarracht na híomhánna uaslódáilte a chrapadh trí scálú agus uasmhéadú a d'fhéadfadh difear a dhéanamh don cháilíocht íomhá a bhraitear. Mura roghnaítear é, uaslódáilfear na híomhánna gan aon athruithe." + }, + "attribute_detail": { + "attr_detail_title": "Teideal Sonraí Tréithe", + "close_button_title": "Cealaigh athruithe agus dún", + "attr_is_owned_by": "Is leis an tréith", + "attr_name_title": "Ní féidir ach carachtair alfa-uimhriúla, colon agus fo-líne a úsáid in ainm na tréithe", + "name": "Ainm", + "value": "Luach", + "target_note_title": "Is nasc ainmnithe idir nóta foinse agus nóta sprice é gaol.", + "target_note": "Nóta sprice", + "promoted_title": "Taispeántar an tréith chun cinn go feiceálach ar an nóta.", + "promoted": "Curtha chun cinn", + "promoted_alias_title": "An t-ainm atá le taispeáint i gcomhéadan úsáideora na dtréithe cur chun cinn.", + "promoted_alias": "Leasainm", + "multiplicity_title": "Sainmhíníonn iolracht cé mhéad tréith den ainm céanna is féidir a chruthú - uasmhéid 1 nó níos mó ná 1.", + "multiplicity": "Ilghnéitheacht", + "single_value": "Luach aonair", + "multi_value": "Illuach", + "label_type_title": "Cabhróidh cineál an lipéid le Trilium comhéadan oiriúnach a roghnú chun luach an lipéid a iontráil.", + "label_type": "Cineál", + "text": "Téacs", + "number": "Uimhir", + "boolean": "Booleánach", + "date": "Date", + "date_time": "Dáta & Am", + "time": "Am", + "url": "URL", + "precision_title": "Cén líon digití i ndiaidh snámhphointe ba chóir a bheith ar fáil sa chomhéadan socraithe luachanna.", + "precision": "Beachtas", + "digits": "digití", + "inverse_relation_title": "Socrú roghnach chun a shainiú cén gaol atá os coinne an ceann seo. Sampla: Is gaolta inbhéartacha iad Athair - Mac lena chéile.", + "inverse_relation": "Gaol inbhéartach", + "inheritable_title": "Déanfar tréith oidhreachtúil a oidhreachtú chuig gach sliocht faoin gcrann seo.", + "inheritable": "Oidhreachtúil", + "save_and_close": "Sábháil & dún Ctrl+Enter", + "delete": "Scrios", + "related_notes_title": "Nótaí eile leis an lipéad seo", + "more_notes": "Tuilleadh nótaí", + "label": "Sonraí lipéid", + "label_definition": "Mionsonraí sainmhínithe lipéid", + "relation": "Sonraí an chaidrimh", + "relation_definition": "Mionsonraí sainmhínithe caidrimh", + "disable_versioning": "díchumasaíonn sé uathleaganú. Úsáideach le haghaidh nótaí móra ach neamhthábhachtacha mar shampla - mar shampla leabharlanna móra JS a úsáidtear le haghaidh scriptithe", + "calendar_root": "nóta marcáilte ar cheart a úsáid mar fhréamh do nótaí lae. Níor cheart ach ceann amháin a mharcáil mar sin.", + "archived": "Ní bheidh nótaí leis an lipéad seo le feiceáil de réir réamhshocraithe i dtorthaí cuardaigh (i ndialóga Léim Chuig, Cuir Nasc Leis srl. chomh maith).", + "exclude_from_export": "ní chuirfear nótaí (lena bhfo-chrann) san áireamh in aon onnmhairiú nótaí", + "run": "Sainmhíníonn sé seo cé na himeachtaí ar cheart don script rith orthu. Is iad seo a leanas na luachanna féideartha:\n
    \n
  • frontendStartup - nuair a thosaíonn (nó a athnuachan) tosaigh Trilium, ach ní ar fhóin phóca.
  • \n
  • mobileStartup - nuair a thosaíonn (nó a athnuachan) tosaigh Trilium, ar fhóin phóca.
  • \n
  • backendStartup - nuair a thosaíonn cúltaca Trilium
  • \n
  • uair an chloig - rith uair san uair. Is féidir leat lipéad breise runAtHour a úsáid chun a shonrú cén uair a ritheann sé.
  • \n
  • daily - rith uair sa lá
  • \n
", + "run_on_instance": "Sainmhínigh cén sampla de Trilium ba chóir é seo a rith air. Réamhshocrú do gach sampla.", + "run_at_hour": "Cén uair ar cheart é seo a rith? Ba cheart é a úsáid i dteannta #run=hourly. Is féidir é seo a shainiú arís agus arís eile le haghaidh níos mó ritheanna i rith an lae.", + "disable_inclusion": "Ní chuirfear scripteanna leis an lipéad seo san áireamh i bhforghníomhú an scripte tuismitheora.", + "sorted": "coinníonn nótaí leanaí sórtáilte de réir teidil in ord aibítre", + "sort_direction": "ASC (an réamhshocrú) nó DESC", + "sort_folders_first": "Ba chóir fillteáin (nótaí le páistí) a shórtáil ar bharr", + "top": "coinnigh an nóta tugtha ag barr a thuismitheora (baineann sé seo le tuismitheoirí sórtáilte amháin)", + "hide_promoted_attributes": "Folaigh tréithe cur chun cinn ar an nóta seo", + "read_only": "Tá an t-eagarthóir i mód léite amháin. Ní oibríonn sé ach le haghaidh téacs agus nótaí cóid.", + "auto_read_only_disabled": "Is féidir nótaí téacs/cód a shocrú go huathoibríoch i mód léite nuair a bhíonn siad rómhór. Is féidir leat an t-iompar seo a dhíchumasú ar bhonn gach nóta tríd an lipéad seo a chur leis an nóta", + "app_css": "marcálann sé nótaí CSS a lódáiltear isteach san fheidhmchlár Trilium agus is féidir iad a úsáid dá bhrí sin chun cuma Trilium a mhodhnú.", + "app_theme": "marcálann sé nótaí CSS ar téamaí iomlána Trilium iad agus atá ar fáil dá bhrí sin i roghanna Trilium.", + "app_theme_base": "socraigh go \"next\", \"next-light\", nó \"next-dark\" chun an téama TriliumNext comhfhreagrach (uathoibríoch, geal nó dorcha) a úsáid mar bhunús do théama saincheaptha, in ionad an cheann oidhreachta.", + "css_class": "Cuirtear luach an lipéid seo leis an nód mar rang CSS ansin, a léiríonn an nóta tugtha sa chrann. Is féidir é seo a bheith úsáideach le haghaidh téamaithe ardleibhéil. Is féidir é a úsáid i nótaí teimpléid.", + "icon_class": "Cuirtear luach an lipéid seo leis an deilbhín ar an gcrann mar rang CSS, rud a chabhróidh le hidirdhealú amhairc a dhéanamh idir na nótaí sa chrann. D’fhéadfadh sampla a bheith ann de bx bx-home - tógtar deilbhíní ó boxicons. Is féidir iad a úsáid i nótaí teimpléid.", + "page_size": "líon na míreanna in aghaidh an leathanaigh i liostú nótaí", + "custom_request_handler": "féach láimhseálaí iarratais saincheaptha", + "custom_resource_provider": "féach láimhseálaí iarratais saincheaptha", + "widget": "marcálann an nóta seo mar ghiuirléid saincheaptha a chuirfear leis an gcrann comhpháirte Trilium", + "workspace": "marcálann an nóta seo mar spás oibre a ligeann d’ardú go héasca", + "workspace_icon_class": "sainmhíníonn sé rang CSS deilbhín bosca a úsáidfear sa chluaisín nuair a ardófar chuig an nóta seo é", + "workspace_tab_background_color": "Dath CSS a úsáidtear sa chluaisín nótaí nuair a ardaítear chuig an nóta seo é", + "workspace_calendar_root": "Sainmhíníonn fréamh féilire in aghaidh an spáis oibre", + "workspace_template": "Beidh an nóta seo le feiceáil i roghnú na dteimpléad atá ar fáil agus nóta nua á chruthú, ach amháin nuair a ardófar isteach i spás oibre ina bhfuil an teimpléad seo é", + "search_home": "Cruthófar nótaí cuardaigh nua mar leanaí den nóta seo", + "workspace_search_home": "Cruthófar nótaí cuardaigh nua mar leanaí den nóta seo nuair a ardófar chuig sinsear éigin den nóta spás oibre seo iad", + "inbox": "Suíomh réamhshocraithe sa bhosca isteach le haghaidh nótaí nua - nuair a chruthaíonn tú nóta ag baint úsáide as an gcnaipe \"nóta nua\" sa bharra taoibh, cruthófar nótaí mar nótaí linbh sa nóta atá marcáilte leis an lipéad #inbox.", + "workspace_inbox": "Suíomh réamhshocraithe sa bhosca isteach le haghaidh nótaí nua nuair a ardaítear chuig sinsear éigin den nóta spás oibre seo iad", + "sql_console_home": "suíomh réamhshocraithe nótaí consól SQL", + "bookmark_folder": "Beidh nóta leis an lipéad seo le feiceáil i leabharmharcanna mar fhillteán (ag tabhairt rochtain ar a leanaí)", + "share_hidden_from_tree": "Tá an nóta seo i bhfolach ón gcrann nascleanúna ar chlé, ach tá sé fós inrochtana lena URL", + "share_external_link": "Feidhmeoidh an nóta mar nasc chuig suíomh Gréasáin seachtrach sa chrann comhroinnte", + "share_alias": "sainigh leasainm trína mbeidh an nóta ar fáil faoi https://your_trilium_host/share/[your_alias]", + "share_omit_default_css": "Fágfar an CSS réamhshocraithe don leathanach comhroinnte ar lár. Bain úsáid as nuair a dhéanann tú athruithe móra ar stíl.", + "share_root": "nóta marcanna a sheirbheáiltear ar /share root.", + "share_description": "sainmhínigh an téacs atá le cur leis an meitea-chlib HTML le haghaidh cur síos", + "share_raw": "Seirbheálfar an nóta ina fhormáid amh, gan fillteán HTML", + "share_disallow_robot_indexing": "cuirfidh sé cosc ar innéacsú róbat an nóta seo tríd an gceannteideal X-Robots-Tag: noindex", + "share_credentials": "Teastaíonn dintiúir chun rochtain a fháil ar an nóta comhroinnte seo. Táthar ag súil go mbeidh an luach san fhormáid 'ainm úsáideora:pasfhocal'. Ná déan dearmad é seo a dhéanamh inoidhreachtúil le cur i bhfeidhm ar nótaí/íomhánna linbh.", + "share_index": "liostálfaidh nóta leis an lipéad seo fréamhacha uile nótaí comhroinnte", + "display_relations": "Ainmneacha caidrimh scartha le camóga ar cheart iad a thaispeáint. Beidh na cinn eile go léir i bhfolach.", + "hide_relations": "Ainmneacha caidrimh scartha le camóga ar cheart iad a cheilt. Taispeánfar na cinn eile go léir.", + "title_template": "teideal réamhshocraithe nótaí a cruthaíodh mar leanaí den nóta seo. Déantar an luach a mheas mar theaghrán JavaScript \n agus dá bhrí sin is féidir é a shaibhriú le hábhar dinimiciúil trí na hathróga now agus parentNote insteallta. Samplaí:\n \n
    \n
  • Saothair liteartha ${parentNote.getLabelValue('authorName')}
  • \n
  • Log le haghaidh ${now.format('YYYY-MM-DD HH:mm:ss')}
  • \n
\n \n Féach vicí le sonraí, doiciméid API le haghaidh parentNote agus now le haghaidh sonraí.", + "template": "Beidh an nóta seo le feiceáil i roghnú na dteimpléad atá ar fáil agus nóta nua á chruthú", + "toc": "Cuirfidh #toc#toc=show iallach ar an gClár Ábhair a bheith le feiceáil, cuirfidh #toc=hide iallach air é a cheilt. Mura bhfuil an lipéad ann, breathnaítear ar an socrú domhanda", + "color": "sainmhíníonn dath an nóta sa chrann nótaí, snaisc srl. Úsáid aon luach datha CSS bailí cosúil le 'dearg' nó #a13d5f", + "keyboard_shortcut": "Sainmhíníonn sé seo aicearra méarchláir a léimfidh láithreach chuig an nóta seo. Sampla: 'ctrl+alt+e'. Éilítear athlódáil an tosaigh chun go dtiocfaidh an t-athrú i bhfeidhm.", + "keep_current_hoisting": "Ní athróidh oscailt an naisc seo an t-ardú fiú mura bhfuil an nóta inléite sa fho-chrann ardaithe reatha.", + "execute_button": "Teideal an chnaipe a fhorghníomhóidh an nóta cóid reatha", + "execute_description": "Cur síos níos faide ar an nóta cóid reatha a thaispeántar in éineacht leis an gcnaipe forghníomhaithe", + "exclude_from_note_map": "Beidh nótaí leis an lipéad seo i bhfolach ón Léarscáil Nótaí", + "new_notes_on_top": "Cruthófar nótaí nua ag barr an nóta tuismitheora, ní ag an mbun.", + "hide_highlight_widget": "Folaigh an giuirléid Liosta Aibhsithe", + "run_on_note_creation": "ritheann nuair a chruthaítear nóta ar an gcúl-deireadh. Úsáid an gaol seo más mian leat an script a rith do gach nóta a cruthaíodh faoi fho-chrann ar leith. Sa chás sin, cruthaigh é ar fhréamhnóta an fho-chrainn agus déan é inoidhreachta. Cuirfidh nóta nua a chruthaítear laistigh den fho-chrann (aon doimhneacht) an script i ngníomh.", + "run_on_child_note_creation": "ritheann sé nuair a chruthaítear nóta nua faoin nóta ina bhfuil an gaol seo sainmhínithe", + "run_on_note_title_change": "forghníomhaítear nuair a athraítear teideal an nóta (lena n-áirítear cruthú nótaí chomh maith)", + "run_on_note_content_change": "forghníomhaítear nuair a athraítear ábhar nótaí (lena n-áirítear cruthú nótaí chomh maith).", + "run_on_note_change": "ritheann nuair a athraítear nóta (áirítear cruthú nótaí leis). Ní áirítear athruithe ar an ábhar", + "run_on_note_deletion": "ritheann sé nuair a scriostar nóta", + "run_on_branch_creation": "ritheann nuair a chruthaítear brainse. Is nasc é brainse idir nóta tuismitheora agus nóta linbh agus cruthaítear é m.sh. nuair a bhíonn nóta á chlónáil nó á bhogadh.", + "run_on_branch_change": "ritheann nuair a dhéantar brainse a nuashonrú.", + "run_on_branch_deletion": "forghníomhaítear nuair a scriostar brainse. Is nasc idir nóta tuismitheora agus nóta linbh í an brainse agus scriostar í m.sh. nuair a bhogtar nóta (scriostar seanbhrainse/nasc).", + "run_on_attribute_creation": "ritheann nuair a chruthaítear tréith nua don nóta a shainmhíníonn an gaol seo", + "run_on_attribute_change": " ritheann nuair a athraítear tréith nóta a shainmhíníonn an gaol seo. Cuirtear i ngníomh é seo freisin nuair a scriostar an tréith", + "relation_template": "Gheobhaidh tréithe an nóta oidhreacht fiú gan caidreamh tuismitheora-linbh, cuirfear ábhar agus fo-chrann an nóta le nótaí sampla má tá siad folamh. Féach ar an doiciméadú le haghaidh sonraí.", + "inherit": "Gheobhaidh tréithe an nóta oidhreacht fiú mura bhfuil caidreamh tuismitheora-linbh ann. Féach caidreamh teimpléid le haghaidh coincheap cosúil leis. Féach oidhreacht tréithe sa doiciméadú.", + "render_note": "Déanfar nótaí den chineál \"render HTML note\" a rindreáil ag baint úsáide as nóta cóid (HTML nó script) agus is gá a léiriú ag baint úsáide as an ngaol seo cén nóta ba chóir a rindreáil", + "widget_relation": "Déanfar sprioc an chaidrimh seo a fhorghníomhú agus a léiriú mar ghiuirléid sa bharra taoibh", + "share_css": "Nóta CSS a chuirfear isteach sa leathanach comhroinnte. Caithfidh nóta CSS a bheith sa fho-chrann comhroinnte chomh maith. Smaoinigh ar 'share_hidden_from_tree' agus 'share_omit_default_css' a úsáid chomh maith.", + "share_js": "Nóta JavaScript a chuirfear isteach sa leathanach comhroinnte. Caithfidh nóta JS a bheith sa fho-chrann comhroinnte chomh maith. Smaoinigh ar 'share_hidden_from_tree' a úsáid.", + "share_template": "Nóta JavaScript leabaithe a úsáidfear mar theimpléad chun an nóta comhroinnte a thaispeáint. Téann sé ar ais go dtí an teimpléad réamhshocraithe. Smaoinigh ar 'share_hidden_from_tree' a úsáid.", + "share_favicon": "Nóta favicon le socrú sa leathanach comhroinnte. De ghnáth ba mhaith leat é a shocrú mar fhréamh comhroinnte agus é a dhéanamh oidhreachtúil. Caithfidh nóta favicon a bheith sa fho-chrann comhroinnte chomh maith. Smaoinigh ar 'share_hidden_from_tree' a úsáid.", + "is_owned_by_note": "is leis an nóta", + "other_notes_with_name": "Nótaí eile leis an ainm \"{{attributeName}}\" ar {{attributeType}}", + "and_more": "... agus {{count}} eile.", + "print_landscape": "Agus é á onnmhairiú go PDF, athraítear treoshuíomh an leathanaigh go tírdhreach seachas portráid.", + "print_page_size": "Agus é á easpórtáil go PDF, athraítear méid an leathanaigh. Luachanna tacaithe: A0, A1, A2, A3, A4, A5, A6, Legal, Letter, Tabloid, Ledger.", + "color_type": "Dath" + }, + "attribute_editor": { + "help_text_body1": "Chun lipéad a chur leis, clóscríobh m.sh. #rock nó más mian leat luach a chur leis freisin ansin m.sh. #year = 2020", + "help_text_body2": "I gcás gaol, clóscríobh ~author = @ rud a thabharfaidh uathchríochnú aníos inar féidir leat an nóta atá uait a chuardach.", + "help_text_body3": "Nó is féidir leat lipéad agus gaol a chur leis trí úsáid a bhaint as an gcnaipe + ar an taobh deas.", + "save_attributes": "Sábháil tréithe ", + "add_a_new_attribute": "Cuir tréith nua leis", + "add_new_label": "Cuir lipéad nua leis ", + "add_new_relation": "Cuir gaol nua leis ", + "add_new_label_definition": "Cuir sainmhíniú lipéid nua leis", + "add_new_relation_definition": "Cuir sainmhíniú caidrimh nua leis", + "placeholder": "Clóscríobh na lipéid agus na caidrimh anseo" + }, + "abstract_bulk_action": { + "remove_this_search_action": "Bain an gníomh cuardaigh seo" + }, + "execute_script": { + "execute_script": "Forghníomhaigh script", + "help_text": "Is féidir leat scripteanna simplí a fhorghníomhú ar na nótaí meaitseáilte.", + "example_1": "Mar shampla, chun teaghrán a chur le teideal nóta, bain úsáid as an script beag seo:", + "example_2": "Sampla níos casta ná tréithe uile an nóta mheaitseáilte a scriosadh:" + }, + "add_label": { + "add_label": "Cuir lipéad leis", + "label_name_placeholder": "ainm lipéid", + "label_name_title": "Is carachtair cheadaithe iad carachtair alfa-uimhriúla, fo-strait agus colon.", + "to_value": "luach a chur", + "new_value_placeholder": "luach nua", + "help_text": "Ar na nótaí uile a mheaitseálann:", + "help_text_item1": "cruthaigh lipéad tugtha mura bhfuil ceann ag an nóta fós", + "help_text_item2": "nó luach an lipéid atá ann cheana a athrú", + "help_text_note": "Is féidir leat an modh seo a ghlaoch gan luach freisin, sa chás sin sanntar lipéad don nóta gan luach." + }, + "delete_label": { + "delete_label": "Scrios lipéad", + "label_name_placeholder": "ainm lipéid", + "label_name_title": "Is carachtair cheadaithe iad carachtair alfa-uimhriúla, fo-strait agus colon." + }, + "rename_label": { + "rename_label": "Athainmnigh an lipéad", + "rename_label_from": "Athainmnigh an lipéad ó", + "old_name_placeholder": "seanainm", + "to": "Chuig", + "new_name_placeholder": "ainm nua", + "name_title": "Is carachtair cheadaithe iad carachtair alfa-uimhriúla, fo-strait agus colon." + }, + "update_label_value": { + "update_label_value": "Nuashonraigh luach an lipéid", + "label_name_placeholder": "ainm lipéid", + "label_name_title": "Is carachtair cheadaithe iad carachtair alfa-uimhriúla, fo-strait agus colon.", + "to_value": "luach a chur", + "new_value_placeholder": "luach nua", + "help_text": "Ar na nótaí uile a mheaitseálann, athraigh luach an lipéid atá ann cheana féin.", + "help_text_note": "Is féidir leat an modh seo a ghlaoch gan luach freisin, sa chás sin sanntar lipéad don nóta gan luach." + }, + "delete_note": { + "delete_note": "Scrios nóta", + "delete_matched_notes": "Scrios nótaí comhoiriúnacha", + "delete_matched_notes_description": "Scriosfaidh sé seo nótaí comhoiriúnacha.", + "undelete_notes_instruction": "Tar éis an scriosta, is féidir iad a athscriosadh ón dialóg Athruithe Le Déanaí.", + "erase_notes_instruction": "Chun nótaí a scriosadh go buan, is féidir leat dul i ndiaidh an scriosta chuig Rogha -> Eile agus cliceáil ar an gcnaipe \"Scrios nótaí scriosta anois\"." + }, + "delete_revisions": { + "delete_note_revisions": "Scrios athbhreithnithe nótaí", + "all_past_note_revisions": "Scriosfar gach athbhreithniú nóta roimhe seo ar nótaí meaitseáilte. Caomhnófar an nóta féin go hiomlán. I dtéarmaí eile, bainfear stair an nóta." + }, + "move_note": { + "move_note": "Bog nóta", + "to": "chuig", + "target_parent_note": "nóta tuismitheora sprice", + "on_all_matched_notes": "Ar na nótaí uile a mheaitseálann", + "move_note_new_parent": "bog nóta chuig an tuismitheoir nua mura bhfuil ach tuismitheoir amháin ag an nóta (i.e. baintear an seanbhrainse agus cruthaítear brainse nua isteach sa tuismitheoir nua)", + "clone_note_new_parent": "nóta clónála chuig an tuismitheoir nua má tá ilchlónanna/brainsí sa nóta (níl sé soiléir cén brainse ba chóir a bhaint)", + "nothing_will_happen": "ní tharlóidh aon rud mura féidir an nóta a bhogadh chuig an nóta sprice (i.e. chruthódh sé seo timthriall crainn)" + }, + "rename_note": { + "rename_note": "Athainmnigh an nóta", + "rename_note_title_to": "Athainmnigh teideal an nóta go", + "new_note_title": "teideal nóta nua", + "click_help_icon": "Cliceáil ar an deilbhín cabhrach ar dheis chun na roghanna go léir a fheiceáil", + "evaluated_as_js_string": "Déantar an luach tugtha a mheas mar theaghrán JavaScript agus dá bhrí sin is féidir é a shaibhriú le hábhar dinimiciúil tríd an athróg note insteallta (nóta á athainmniú). Samplaí:", + "example_note": "Nóta - athainmnítear na nótaí uile a mheaitseálann go 'Nóta'", + "example_new_title": "NUA: ${note.title} - cuirtear 'NUA:' roimh theidil nótaí meaitseáilte", + "example_date_prefix": "${note.dateCreatedObj.format('MM-DD:')}: ${note.title} - cuirtear réimír mhí-dháta cruthaithe an nóta leis na nótaí meaitseáilte", + "api_docs": "Féach ar dhoiciméid API le haghaidh nóta agus a airíonna dateCreatedObj / utcDateCreatedObj le haghaidh tuilleadh sonraí." + }, + "add_relation": { + "add_relation": "Cuir gaol leis", + "relation_name": "ainm an chaidrimh", + "allowed_characters": "Is carachtair cheadaithe iad carachtair alfa-uimhriúla, fo-strait agus colon.", + "to": "chuig", + "target_note": "nóta sprice", + "create_relation_on_all_matched_notes": "Ar na nótaí meaitseáilte uile, cruthaigh gaol tugtha." + }, + "delete_relation": { + "delete_relation": "Scrios an gaol", + "relation_name": "ainm an chaidrimh", + "allowed_characters": "Is carachtair cheadaithe iad carachtair alfa-uimhriúla, fo-strait agus colon." + }, + "rename_relation": { + "rename_relation": "Athainmnigh an gaol", + "rename_relation_from": "Athainmnigh an gaol ó", + "old_name": "seanainm", + "to": "Chuig", + "new_name": "ainm nua", + "allowed_characters": "Is carachtair cheadaithe iad carachtair alfa-uimhriúla, fo-strait agus colon." + }, + "update_relation_target": { + "update_relation": "Nuashonraigh an gaol", + "relation_name": "ainm an chaidrimh", + "allowed_characters": "Is carachtair cheadaithe iad carachtair alfa-uimhriúla, fo-strait agus colon.", + "to": "chuig", + "target_note": "nóta sprice", + "on_all_matched_notes": "Ar na nótaí uile a mheaitseálann", + "change_target_note": "athrú nóta sprice an chaidrimh atá ann cheana", + "update_relation_target": "Nuashonraigh sprioc an chaidrimh" + }, + "attachments_actions": { + "open_externally": "Oscail go seachtrach", + "open_externally_title": "Osclófar an comhad in feidhmchlár seachtrach agus beidh súil ghéar air le haghaidh athruithe. Beidh tú in ann an leagan modhnaithe a uaslódáil ar ais chuig Trilium ansin.", + "open_custom": "Oscail saincheaptha", + "open_custom_title": "Osclófar an comhad in feidhmchlár seachtrach agus beidh súil ghéar air le haghaidh athruithe. Beidh tú in ann an leagan modhnaithe a uaslódáil ar ais chuig Trilium ansin.", + "download": "Íoslódáil", + "rename_attachment": "Athainmnigh an ceangaltán", + "upload_new_revision": "Uaslódáil athbhreithniú nua", + "copy_link_to_clipboard": "Cóipeáil nasc chuig an ghearrthaisce", + "convert_attachment_into_note": "Tiontaigh an ceangaltán ina nóta", + "delete_attachment": "Scrios an ceangaltán", + "upload_success": "Tá athbhreithniú nua ar an gceangaltán uaslódáilte.", + "upload_failed": "Theip ar uaslódáil athbhreithniú nua ar cheangaltán.", + "open_externally_detail_page": "Ní féidir ceangaltán a oscailt go seachtrach ach ón leathanach sonraí, cliceáil ar shonraí an cheangaltáin ar dtús agus déan an gníomh arís.", + "open_custom_client_only": "Ní féidir ceangaltáin a oscailt go saincheaptha ach amháin ón gcliant deisce.", + "delete_confirm": "An bhfuil tú cinnte gur mian leat an ceangaltán '{{title}}' a scriosadh?", + "delete_success": "Scriosadh an ceangaltán '{{title}}'.", + "convert_confirm": "An bhfuil tú cinnte gur mian leat an ceangaltán '{{title}}' a thiontú ina nóta ar leith?", + "convert_success": "Tá an ceangaltán '{{title}}' tiontaithe go nóta.", + "enter_new_name": "Cuir isteach ainm an cheangaltáin nua le do thoil" + }, + "calendar": { + "mon": "Lua", + "tue": "Mai", + "wed": "Céa", + "thu": "Déa", + "fri": "Aoi", + "sat": "Sat", + "sun": "Dom", + "cannot_find_day_note": "Ní féidir nóta lae a aimsiú", + "cannot_find_week_note": "Ní féidir nóta seachtaine a aimsiú", + "january": "Eanáir", + "february": "Feabhra", + "march": "Márta", + "april": "Aibreán", + "may": "Bealtaine", + "june": "Meitheamh", + "july": "Iúil", + "august": "Lúnasa", + "september": "Meán Fómhair", + "october": "Deireadh Fómhair", + "november": "Samhain", + "december": "Nollaig", + "week": "Seachtain", + "week_previous": "An tseachtain roimhe sin", + "week_next": "An tseachtain seo chugainn", + "month": "Mí", + "month_previous": "An mhí roimhe sin", + "month_next": "An mhí seo chugainn", + "year": "Bliain", + "year_previous": "An bhliain roimhe sin", + "year_next": "An bhliain seo chugainn", + "list": "Liosta", + "today": "Inniu" + }, + "close_pane_button": { + "close_this_pane": "Dún an phainéal seo" + }, + "create_pane_button": { + "create_new_split": "Cruthaigh scoilt nua" + }, + "edit_button": { + "edit_this_note": "Cuir an nóta seo in eagar" + }, + "show_toc_widget_button": { + "show_toc": "Taispeáin Clár Ábhair" + }, + "show_highlights_list_widget_button": { + "show_highlights_list": "Taispeáin Liosta Buaicphointí" + }, + "zen_mode": { + "button_exit": "Scoir Mód Zen" + }, + "sync_status": { + "unknown": "

Beidh stádas an sioncrónaithe ar eolas a luaithe a thosóidh an chéad iarracht sioncrónaithe eile.

Cliceáil chun sioncrónú a spreagadh anois.

", + "connected_with_changes": "

Ceangailte leis an bhfreastalaí sioncrónaithe.
Tá roinnt athruithe le sioncrónú fós.

Cliceáil chun sioncrónú a spreagadh.

", + "connected_no_changes": "

Ceangailte leis an bhfreastalaí sioncrónaithe.
Tá na hathruithe go léir sioncrónaithe cheana féin.

Cliceáil chun sioncrónú a spreagadh.

", + "disconnected_with_changes": "

Níor éirigh leis an nasc leis an bhfreastalaí sioncrónaithe a bhunú.
Tá roinnt athruithe le sioncrónú fós.

Cliceáil chun sioncrónú a ghníomhachtú.

", + "disconnected_no_changes": "

Níor éirigh leis an nasc leis an bhfreastalaí sioncrónaithe a bhunú.
Tá na hathruithe ar fad aitheanta sioncrónaithe.

Cliceáil chun sioncrónú a spreagadh.

", + "in_progress": "Tá sioncrónú leis an bhfreastalaí ar siúl." + }, + "left_pane_toggle": { + "show_panel": "Taispeáin an painéal", + "hide_panel": "Folaigh an painéal" + }, + "move_pane_button": { + "move_left": "Bog ar chlé", + "move_right": "Bog ar dheis" + }, + "note_actions": { + "convert_into_attachment": "Tiontaigh ina cheangaltán", + "re_render_note": "Ath-rindreáil nóta", + "search_in_note": "Cuardaigh sa nóta", + "note_source": "Foinse nóta", + "note_attachments": "Ceangaltáin nótaí", + "open_note_externally": "Oscail nóta go seachtrach", + "open_note_externally_title": "Osclófar an comhad in feidhmchlár seachtrach agus beidh súil ghéar air le haghaidh athruithe. Beidh tú in ann an leagan modhnaithe a uaslódáil ar ais chuig Trilium ansin.", + "open_note_custom": "Oscail nóta saincheaptha", + "open_note_on_server": "Oscail nóta ar an bhfreastalaí", + "import_files": "Iompórtáil comhaid", + "export_note": "Nóta easpórtála", + "delete_note": "Scrios nóta", + "print_note": "Priontáil nóta", + "view_revisions": "Tabhair faoi deara athbhreithnithe...", + "save_revision": "Sábháil athbhreithniú", + "advanced": "Ardleibhéil", + "convert_into_attachment_failed": "Theip ar nóta '{{title}}' a thiontú.", + "convert_into_attachment_successful": "Tá an nóta '{{title}}' tiontaithe go ceangaltán.", + "convert_into_attachment_prompt": "An bhfuil tú cinnte gur mian leat an nóta '{{title}}' a thiontú ina cheangaltán den nóta tuismitheora?", + "print_pdf": "Easpórtáil mar PDF...", + "export_as_image": "Easpórtáil mar íomhá", + "export_as_image_png": "PNG (rastar)", + "export_as_image_svg": "SVG (veicteoir)", + "note_map": "Léarscáil nótaí" + }, + "onclick_button": { + "no_click_handler": "Níl aon láimhseálaí cliceáil sainithe ag an ngiuirléid cnaipe '{{componentId}}'" + }, + "protected_session_status": { + "active": "Tá an seisiún cosanta gníomhach. Cliceáil chun an seisiún cosanta a fhágáil.", + "inactive": "Cliceáil chun dul isteach i seisiún faoi chosaint" + }, + "revisions_button": { + "note_revisions": "Athbhreithnithe Nótaí" + }, + "update_available": { + "update_available": "Nuashonrú ar fáil" + }, + "note_launcher": { + "this_launcher_doesnt_define_target_note": "Ní shainíonn an lainseálaí seo nóta sprice." + }, + "code_buttons": { + "execute_button_title": "Rith an script", + "trilium_api_docs_button_title": "Oscail doiciméid API Trilium", + "save_to_note_button_title": "Sábháil chuig nóta", + "opening_api_docs_message": "Ag oscailt doiciméid API...", + "sql_console_saved_message": "Tá nóta Consól SQL sábháilte i {{note_path}}" + }, + "copy_image_reference_button": { + "button_title": "Cóipeáil tagairt íomhá chuig an ghearrthaisce, is féidir é a ghreamú i nóta téacs." + }, + "hide_floating_buttons_button": { + "button_title": "Folaigh cnaipí" + }, + "show_floating_buttons_button": { + "button_title": "Taispeáin cnaipí" + }, + "svg_export_button": { + "button_title": "Easpórtáil léaráid mar SVG" + }, + "relation_map_buttons": { + "reset_pan_zoom_title": "Athshocraigh panáil agus súmáil go dtí na comhordanáidí agus an formhéadú tosaigh", + "zoom_in_title": "Zúmáil Isteach", + "zoom_out_title": "Zúmáil Amach", + "create_child_note_title": "Cruthaigh nóta linbh agus cuir leis an léarscáil é" + }, + "zpetne_odkazy": { + "backlink_one": "{{count}} Nasc siar", + "backlink_two": "{{count}} Naisc siar", + "backlink_few": "{{count}} Naisc siar", + "backlink_many": "{{count}} Naisc siar", + "backlink_other": "{{count}} Naisc siar", + "relation": "gaol" + }, + "mobile_detail_menu": { + "insert_child_note": "Cuir nóta linbh isteach", + "delete_this_note": "Scrios an nóta seo", + "note_revisions": "Athbhreithnithe nóta", + "error_cannot_get_branch_id": "Ní féidir aitheantas brainse a fháil do NotePad '{{notePath}}'", + "error_unrecognized_command": "Ordú gan aitheantas {{command}}", + "backlinks": "Naisc ar ais", + "content_language_switcher": "Teanga an ábhair: {{language}}" + }, + "note_icon": { + "change_note_icon": "Deilbhín nóta athraithe", + "search": "Cuardaigh:", + "search_placeholder_one": "Cuardaigh deilbhíní {{number}} ar fud pacáistí {{count}}", + "search_placeholder_two": "Cuardaigh deilbhíní {{number}} ar fud pacáistí {{count}}", + "search_placeholder_few": "Cuardaigh deilbhíní {{number}} ar fud pacáistí {{count}}", + "search_placeholder_many": "Cuardaigh deilbhíní {{number}} ar fud pacáistí {{count}}", + "search_placeholder_other": "Cuardaigh deilbhíní {{number}} ar fud pacáistí {{count}}", + "search_placeholder_filtered": "Cuardaigh deilbhíní {{number}} i {{name}}", + "reset-default": "Athshocraigh go dtí an deilbhín réamhshocraithe", + "filter": "Scagaire", + "filter-none": "Gach deilbhín", + "filter-default": "Deilbhíní réamhshocraithe", + "icon_tooltip": "{{name}}\nPacáiste deilbhín: {{iconPack}}", + "no_results": "Níor aimsíodh aon deilbhíní." + }, + "basic_properties": { + "note_type": "Cineál nóta", + "editable": "In-eagarthóireacht", + "basic_properties": "Airíonna Bunúsacha", + "language": "Teanga", + "configure_code_notes": "Cumraigh nótaí cóid..." + }, + "book_properties": { + "view_type": "Cineál radhairc", + "grid": "Eangach", + "list": "Liosta", + "collapse_all_notes": "Laghdaigh na nótaí go léir", + "expand_tooltip": "Leathnaíonn sé seo na páistí díreacha den bhailiúchán seo (leibhéal amháin domhain). Chun níos mó roghanna a fháil, brúigh an tsaighead ar dheis.", + "collapse": "Laghdaigh", + "expand": "Leathnaigh", + "expand_first_level": "Leathnaigh leanaí díreacha", + "expand_nth_level": "Leathnaigh leibhéil {{depth}}", + "expand_all_levels": "Leathnaigh gach leibhéal", + "book_properties": "Airíonna an Bhailiúcháin", + "invalid_view_type": "Cineál radhairc neamhbhailí '{{type}}'", + "calendar": "Féilire", + "table": "Tábla", + "geo-map": "Léarscáil Gheografach", + "board": "Bord", + "presentation": "Cur i Láthair", + "include_archived_notes": "Taispeáin nótaí cartlannaithe", + "hide_child_notes": "Folaigh nótaí leanaí sa chrann" + }, + "edited_notes": { + "no_edited_notes_found": "Gan aon nótaí eagarthóireachta ar an lá seo go fóill...", + "title": "Nótaí Eagarthóireachta", + "deleted": "(scriosta)" + }, + "file_properties": { + "note_id": "Aitheantas Nóta", + "original_file_name": "Ainm comhaid bunaidh", + "file_type": "Cineál comhaid", + "file_size": "Méid comhaid", + "download": "Íoslódáil", + "open": "Oscail go seachtrach", + "upload_new_revision": "Uaslódáil athbhreithniú nua", + "upload_success": "Tá athbhreithniú comhaid nua uaslódáilte.", + "upload_failed": "Theip ar uaslódáil athbhreithniú comhaid nua.", + "title": "Comhad" + }, + "image_properties": { + "original_file_name": "Ainm comhaid bunaidh", + "file_type": "Cineál comhaid", + "file_size": "Méid comhaid", + "download": "Íoslódáil", + "open": "Oscail", + "copy_reference_to_clipboard": "Cóipeáil tagairt chuig an ghearrthaisce", + "upload_new_revision": "Uaslódáil athbhreithniú nua", + "upload_success": "Tá athbhreithniú nua íomhá uaslódáilte.", + "upload_failed": "Theip ar uaslódáil athbhreithniú íomhá nua: {{message}}", + "title": "Íomhá" + }, + "inherited_attribute_list": { + "title": "Tréithe Oidhreachta", + "no_inherited_attributes": "Gan aon tréithe oidhreachta.", + "none": "aon cheann" + }, + "note_info_widget": { + "note_id": "Aitheantas Nóta", + "created": "Cruthaithe", + "modified": "Modhnaithe", + "type": "Cineál", + "mime": "Cineál MIME", + "note_size": "Méid nóta", + "note_size_info": "Tugann méid an nóta meastachán garbh ar riachtanais stórála don nóta seo. Cuirtear ábhar an nóta agus ábhar a athbhreithnithe nótaí san áireamh ann.", + "calculate": "ríomh", + "subtree_size": "(méid fo-chrainn: {{size}} i nótaí {{count}})", + "title": "Eolas Nóta", + "show_similar_notes": "Taispeáin nótaí comhchosúla" + }, + "note_map": { + "open_full": "Leathnaigh go hiomlán", + "collapse": "Laghdaigh go dtí an gnáthmhéid", + "title": "Léarscáil Nótaí", + "fix-nodes": "Deisigh nóid", + "link-distance": "Fad naisc" + }, + "note_paths": { + "title": "Cosáin Nótaí", + "clone_button": "Nóta clónáilte chuig suíomh nua...", + "intro_placed": "Cuirtear an nóta seo sna cosáin seo a leanas:", + "intro_not_placed": "Níl an nóta seo curtha sa chrann nótaí go fóill.", + "outside_hoisted": "Tá an cosán seo lasmuigh den nóta ardaithe agus bheadh ort é a dhíardú.", + "archived": "Cartlannaithe", + "search": "Cuardaigh" + }, + "note_properties": { + "this_note_was_originally_taken_from": "Tógadh an nóta seo ar dtús ó:", + "info": "Eolas" + }, + "owned_attribute_list": { + "owned_attributes": "Tréithe faoi Úinéireacht" + }, + "promoted_attributes": { + "promoted_attributes": "Tréithe Curtha Chun Cinn", + "unset-field-placeholder": "gan socrú", + "url_placeholder": "http://suíomh gréasáin...", + "open_external_link": "Oscail nasc seachtrach", + "unknown_label_type": "Cineál lipéid anaithnid '{{type}}'", + "unknown_attribute_type": "Cineál tréith anaithnid '{{type}}'", + "add_new_attribute": "Cuir tréith nua leis", + "remove_this_attribute": "Bain an tréith seo", + "remove_color": "Bain an lipéad datha" + }, + "script_executor": { + "query": "Iarratas", + "script": "Script", + "execute_query": "Cuir Iarratas i bhFeidhm", + "execute_script": "Rith an Script" + }, + "search_definition": { + "add_search_option": "Cuir rogha cuardaigh leis:", + "search_string": "teaghrán cuardaigh", + "search_script": "script cuardaigh", + "ancestor": "sinsear", + "fast_search": "cuardach tapa", + "fast_search_description": "Díchumasaíonn an rogha cuardaigh thapa cuardach iomlán ar ábhar nótaí rud a d’fhéadfadh luas a chur le cuardach i mbunachair shonraí móra.", + "include_archived": "cuir cartlannaithe san áireamh", + "include_archived_notes_description": "De réir réamhshocraithe, eisiatar nótaí cartlannaithe ó thorthaí cuardaigh, agus leis an rogha seo cuirfear san áireamh iad.", + "order_by": "ordú de réir", + "limit": "teorainn", + "limit_description": "Teorainn a chur le líon na dtorthaí", + "debug": "dífhabhtú", + "debug_description": "Priontálfaidh Debug faisnéis bhreise dífhabhtaithe isteach sa chonsól chun cabhrú le fiosrúcháin chasta a dhífhabhtú", + "action": "gníomh", + "search_button": "Cuardaigh", + "search_execute": "Gníomhartha Cuardaigh & Forghníomhaithe", + "save_to_note": "Sábháil chuig nóta", + "search_parameters": "Paraiméadair Chuardaigh", + "unknown_search_option": "Rogha cuardaigh anaithnid {{searchOptionName}}", + "search_note_saved": "Tá an nóta cuardaigh sábháilte i {{- notePathTitle}}", + "actions_executed": "Tá gníomhartha curtha i gcrích.", + "view_options": "Roghanna féachana:", + "option": "rogha" + }, + "similar_notes": { + "title": "Nótaí Comhchosúla", + "no_similar_notes_found": "Níor aimsíodh aon nótaí comhchosúla." + }, + "abstract_search_option": { + "remove_this_search_option": "Bain an rogha cuardaigh seo", + "failed_rendering": "Theip ar an rogha cuardaigh rindreála: {{dto}} le hearráid: {{error}} {{stack}}" + }, + "ancestor": { + "label": "Sinsear", + "placeholder": "cuardach nóta de réir a ainm", + "depth_label": "doimhneacht", + "depth_doesnt_matter": "níl aon tábhacht leis", + "depth_eq": "is é {{count}} go díreach", + "direct_children": "páistí díreacha", + "depth_gt": "níos mó ná {{count}}", + "depth_lt": "is lú ná {{count}}" + }, + "debug": { + "debug": "Dífhabhtú", + "debug_info": "Priontálfaidh Debug faisnéis bhreise dífhabhtaithe isteach sa chonsól chun cabhrú le fiosrúcháin chasta a dhífhabhtú.", + "access_info": "Chun rochtain a fháil ar an bhfaisnéis dífhabhtaithe, cuir an fiosrúchán i gcrích agus cliceáil ar \"Taispeáin log an chúltaca\" sa chúinne uachtarach ar chlé." + }, + "fast_search": { + "fast_search": "Cuardach tapa", + "description": "Díchumasaíonn an rogha cuardaigh thapa cuardach iomlán ar ábhar nótaí rud a d’fhéadfadh luas a chur le cuardach i mbunachair shonraí móra." + }, + "include_archived_notes": { + "include_archived_notes": "Cuir nótaí cartlannaithe san áireamh" + }, + "limit": { + "limit": "Teorainn", + "take_first_x_results": "Glac na chéad X torthaí sonraithe amháin." + }, + "order_by": { + "order_by": "Ordú de réir", + "relevancy": "Ábharthacht (réamhshocraithe)", + "title": "Teideal", + "date_created": "Dáta cruthaithe", + "date_modified": "Dáta an mhodhnaithe dheireanaigh", + "content_size": "Méid ábhar nóta", + "content_and_attachments_size": "Méid ábhar nótaí lena n-áirítear ceangaltáin", + "content_and_attachments_and_revisions_size": "Tabhair faoi deara méid an ábhair lena n-áirítear ceangaltáin agus athbhreithnithe", + "revision_count": "Líon na n-athbhreithnithe", + "children_count": "Líon na nótaí leanaí", + "parent_count": "Líon na gclón", + "owned_label_count": "Líon na lipéid", + "owned_relation_count": "Líon na gcaidreamh", + "target_relation_count": "Líon na gcaidreamh atá dírithe ar an nóta", + "random": "Ord randamach", + "asc": "Ag dul suas (réamhshocraithe)", + "desc": "Ag dul síos" + }, + "search_script": { + "title": "Script cuardaigh:", + "placeholder": "cuardach nóta de réir a ainm", + "description1": "Ligeann script cuardaigh torthaí cuardaigh a shainiú trí script a rith. Soláthraíonn sé seo an tsolúbthacht uasta nuair nach leor cuardach caighdeánach.", + "description2": "Ní mór don script cuardaigh a bheith den chineál \"cód\" agus den fhochineál \"JavaScript backend\". Caithfidh an script sraith de nótaí aitheantóirí nó nótaí a thabhairt ar ais.", + "example_title": "Féach ar an sampla seo:", + "example_code": "// 1. réamh-scagadh ag baint úsáide as cuardach caighdeánach\nconst candidateNotes = api.searchForNotes(\"#iris\");\n\n// 2. critéir chuardaigh saincheaptha a chur i bhfeidhm\nconst matchedNotes = candidateNotes\n.filter(note => note.title.match(/[0-9]{1,2}\\. ?[0-9]{1,2}\\. ?[0-9]{4}/));\n\nreturn matchedNotes;", + "note": "Tabhair faoi deara nach féidir an script cuardaigh agus an teaghrán cuardaigh a chomhcheangal le chéile." + }, + "search_string": { + "title_column": "Teaghrán cuardaigh:", + "placeholder": "eochairfhocail lántéacs, #tag = luach...", + "search_syntax": "Comhréir cuardaigh", + "also_see": "féach freisin", + "complete_help": "cabhair iomlán ar chomhréir chuardaigh", + "full_text_search": "Níl le déanamh ach aon téacs a iontráil le haghaidh cuardach téacs iomlán", + "label_abc": "nótaí ar ais leis an lipéad abc", + "label_year": "nótaí a mheaitseálann le bliain lipéid a bhfuil luach 2019 acu", + "label_rock_pop": "nótaí a bhfuil lipéid rac-cheoil agus pop orthu araon", + "label_rock_or_pop": "ní mór ach ceann amháin de na lipéid a bheith i láthair", + "label_year_comparison": "comparáid uimhriúil (chomh maith >, >=, <).", + "label_date_created": "nótaí a cruthaíodh sa mhí seo caite", + "error": "Earráid chuardaigh: {{error}}", + "search_prefix": "Cuardaigh:" + }, + "attachment_detail": { + "open_help_page": "Oscail leathanach cabhrach ar cheangaltáin", + "owning_note": "Nóta úinéireachta: ", + "you_can_also_open": ", is féidir leat an oscailt freisin ", + "list_of_all_attachments": "Liosta de na ceangaltáin uile", + "attachment_deleted": "Scriosadh an ceangaltán seo." + }, + "attachment_list": { + "open_help_page": "Oscail leathanach cabhrach ar cheangaltáin", + "owning_note": "Nóta úinéireachta: ", + "upload_attachments": "Uaslódáil ceangaltáin", + "no_attachments": "Níl aon cheangaltáin leis an nóta seo." + }, + "book": { + "no_children_help": "Níl aon nótaí faoi mhíbhuntáiste sa bhailiúchán seo mar sin níl aon rud le taispeáint.", + "drag_locked_title": "Glasáilte le haghaidh eagarthóireachta", + "drag_locked_message": "Ní cheadaítear tarraingt ós rud é go bhfuil an bailiúchán faoi ghlas le haghaidh eagarthóireachta." + }, + "editable_code": { + "placeholder": "Clóscríobh ábhar do nóta cóid anseo..." + }, + "editable_text": { + "placeholder": "Clóscríobh ábhar do nóta anseo...", + "editor_crashed_title": "Thuairteáil an t-eagarthóir téacs", + "editor_crashed_content": "Aisghabhadh d’ábhar go rathúil, ach b’fhéidir nár sábháladh cuid de do chuid athruithe is déanaí.", + "editor_crashed_details_button": "Féach tuilleadh sonraí...", + "editor_crashed_details_intro": "Má bhíonn an earráid seo agat arís agus arís eile, smaoinigh ar í a thuairisciú ar GitHub tríd an bhfaisnéis thíos a ghreamú.", + "editor_crashed_details_title": "Faisnéis theicniúil", + "auto-detect-language": "Braite go huathoibríoch", + "keeps-crashing": "Tá an chomhpháirt eagarthóireachta ag tuairteáil i gcónaí. Déan iarracht Trilium a atosú. Má leanann an fhadhb, smaoinigh ar thuairisc fabht a chruthú." + }, + "empty": { + "open_note_instruction": "Oscail nóta trí theideal an nóta a chlóscríobh sa bhosca ionchuir thíos nó roghnaigh nóta sa chrann.", + "search_placeholder": "cuardach a dhéanamh ar nóta de réir a ainm", + "enter_workspace": "Cuir isteach spás oibre {{title}}" + }, + "file": { + "file_preview_not_available": "Níl réamhamharc comhaid ar fáil don fhormáid comhaid seo.", + "too_big": "Ní thaispeánann an réamhamharc ach na chéad {{maxNumChars}} carachtar den chomhad ar chúiseanna feidhmíochta. Íoslódáil an comhad agus oscail go seachtrach é le go mbeidh tú in ann an t-ábhar iomlán a fheiceáil." + }, + "protected_session": { + "enter_password_instruction": "Éilíonn tú do phasfhocal a iontráil chun nóta faoi chosaint a thaispeáint:", + "start_session_button": "Tosaigh seisiún faoi chosaint", + "started": "Tá seisiún faoi chosaint tosaithe.", + "wrong_password": "Pasfhocal mícheart.", + "protecting-finished-successfully": "Críochnaíodh an chosaint go rathúil.", + "unprotecting-finished-successfully": "Críochnaíodh an díchosaint go rathúil.", + "protecting-in-progress": "Cosaint ar siúl: {{count}}", + "unprotecting-in-progress-count": "Díchosaint ar siúl: {{count}}", + "protecting-title": "Stádas cosanta", + "unprotecting-title": "Stádas díchosanta" + }, + "relation_map": { + "open_in_new_tab": "Oscail i gcluaisín nua", + "remove_note": "Bain nóta", + "edit_title": "Cuir an teideal in eagar", + "rename_note": "Athainmnigh an nóta", + "enter_new_title": "Cuir isteach teideal nua an nóta:", + "remove_relation": "Bain an gaol", + "confirm_remove_relation": "An bhfuil tú cinnte gur mian leat an gaol a bhaint?", + "specify_new_relation_name": "Sonraigh ainm an chaidrimh nua (carachtair cheadaithe: alfa-uimhriúla, colon agus fo-líne):", + "connection_exists": "Tá nasc '{{name}}' idir na nótaí seo ann cheana féin.", + "start_dragging_relations": "Tosaigh ag tarraingt caidrimh as seo agus scaoil iad ar nóta eile.", + "note_not_found": "Nóta {{noteId}} gan aimsiú!", + "cannot_match_transform": "Ní féidir an claochlú a mheaitseáil: {{transform}}", + "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" + }, + "backend_log": { + "refresh": "Athnuachan" + }, + "consistency_checks": { + "title": "Seiceálacha Comhsheasmhachta", + "find_and_fix_button": "Fadhbanna comhsheasmhachta a aimsiú agus a shocrú", + "finding_and_fixing_message": "Fadhbanna comhsheasmhachta a aimsiú agus a shocrú...", + "issues_fixed_message": "Tá aon fhadhb chomhsheasmhachta a d'fhéadfadh a bheith aimsithe socraithe anois." + }, + "database_anonymization": { + "title": "Anaithnidiú Bunachar Sonraí", + "full_anonymization": "Anaithnidiú Iomlán", + "full_anonymization_description": "Cruthóidh an gníomh seo cóip nua den bhunachar sonraí agus déanfaidh sé anaithnidiú air (bainfear gach ábhar nótaí agus fágfar struchtúr agus roinnt meiteashonraí neamhíogaire amháin) le go mbeidh sé in ann é a roinnt ar líne chun críocha dífhabhtaithe gan eagla go sceithfidh tú do shonraí pearsanta.", + "save_fully_anonymized_database": "Sábháil bunachar sonraí lán-anaithnid", + "light_anonymization": "Anaithnidiú Éadrom", + "light_anonymization_description": "Cruthóidh an gníomh seo cóip nua den bhunachar sonraí agus déanfaidh sé beagán anaithnidithe air — go sonrach ní bhainfear ach ábhar na nótaí go léir, ach fanfaidh teidil agus tréithe. Ina theannta sin, fanfaidh nótaí scripte tosaigh/cúil JS saincheaptha agus giuirléidí saincheaptha. Soláthraíonn sé seo níos mó comhthéacs chun na fadhbanna a dhífhabhtú.", + "choose_anonymization": "Is féidir leat cinneadh a dhéanamh duit féin an mian leat bunachar sonraí atá anaithnid go hiomlán nó beagán gan ainm a sholáthar. Tá fiú bunachar sonraí atá anaithnid go hiomlán an-úsáideach, ach i gcásanna áirithe is féidir le bunachar sonraí atá anaithnid go héadrom an próiseas chun fabhtanna a aithint agus a shocrú a bhrostú.", + "save_lightly_anonymized_database": "Sábháil bunachar sonraí atá anaithnidithe go héadrom", + "existing_anonymized_databases": "Bunachair shonraí gan ainm atá ann cheana féin", + "creating_fully_anonymized_database": "Ag cruthú bunachar sonraí lán-anaithnidithe...", + "creating_lightly_anonymized_database": "Ag cruthú bunachar sonraí atá beagán anaithnidithe...", + "error_creating_anonymized_database": "Níorbh fhéidir bunachar sonraí gan ainm a chruthú, seiceáil logaí an chúltaca le haghaidh sonraí", + "successfully_created_fully_anonymized_database": "Cruthaíodh bunachar sonraí lán-anaithnid i {{anonymizedFilePath}}", + "successfully_created_lightly_anonymized_database": "Cruthaíodh bunachar sonraí atá beagán anaithnid i {{anonymizedFilePath}}", + "no_anonymized_database_yet": "Gan aon bhunachar sonraí anaithnidithe go fóill." + }, + "database_integrity_check": { + "title": "Seiceáil Ionracais Bunachar Sonraí", + "description": "Déanfaidh sé seo seiceáil nach bhfuil an bunachar sonraí truaillithe ar leibhéal SQLite. D’fhéadfadh sé go dtógfadh sé tamall, ag brath ar mhéid an bhunachair shonraí.", + "check_button": "Seiceáil sláine an bhunachair shonraí", + "checking_integrity": "Ag seiceáil sláine an bhunachair shonraí...", + "integrity_check_succeeded": "D’éirigh leis an tseiceáil ionracais - níor aimsíodh aon fhadhbanna.", + "integrity_check_failed": "Theip ar an tseiceáil ionracais: {{results}}" + }, + "sync": { + "title": "Sioncrónaigh", + "force_full_sync_button": "Fórsaigh sioncrónú iomlán", + "fill_entity_changes_button": "Líon taifid athruithe eintitis", + "full_sync_triggered": "Sioncrónú iomlán curtha i ngníomh", + "filling_entity_changes": "Líonadh sraitheanna athruithe eintiteas...", + "sync_rows_filled_successfully": "Líontar na sraitheanna sioncrónaithe go rathúil", + "finished-successfully": "Críochnaíodh an sioncrónú go rathúil.", + "failed": "Theip ar an sioncrónú: {{message}}" + }, + "vacuum_database": { + "title": "Bunachar Sonraí Folúis", + "description": "Déanfaidh sé seo an bunachar sonraí a atógáil agus de ghnáth beidh comhad bunachar sonraí níos lú mar thoradh air. Ní athrófar aon sonraí i ndáiríre.", + "button_text": "Bunachar sonraí folúis", + "vacuuming_database": "Bunachar sonraí folúsghlanadh...", + "database_vacuumed": "Tá an bunachar sonraí folúsghlanaithe" + }, + "experimental_features": { + "title": "Roghanna Turgnamhacha", + "disclaimer": "Is roghanna turgnamhacha iad seo agus d’fhéadfadh éagobhsaíocht a bheith mar thoradh orthu. Bain úsáid astu go cúramach.", + "new_layout_name": "Leagan Amach Nua", + "new_layout_description": "Bain triail as an leagan amach nua le haghaidh cuma níos nua-aimseartha agus inúsáidteachta feabhsaithe. Tá sé faoi réir athruithe móra sna heisiúintí atá le teacht." + }, + "fonts": { + "theme_defined": "Téama sainmhínithe", + "fonts": "Clónna", + "main_font": "Príomhchló", + "font_family": "Teaghlach clónna", + "size": "Méid", + "note_tree_font": "Cló Crann Nótaí", + "note_detail_font": "Cló Sonraí Nóta", + "monospace_font": "Cló Aonspáis (cód)", + "note_tree_and_detail_font_sizing": "Tabhair faoi deara go bhfuil méid an chló crainn agus mionsonraí i gcoibhneas leis an bpríomhshocrú méid cló.", + "not_all_fonts_available": "B’fhéidir nach bhfuil na clónna uile atá liostaithe ar fáil ar do chóras.", + "apply_font_changes": "Chun athruithe cló a chur i bhfeidhm, cliceáil ar", + "reload_frontend": "athlódáil tosaigh", + "generic-fonts": "Clónna ginearálta", + "sans-serif-system-fonts": "Clónna córais Sans-serif", + "serif-system-fonts": "Clónna córais Serif", + "monospace-system-fonts": "Clónna córais aonspáis", + "handwriting-system-fonts": "Clónna córais lámhscríbhneoireachta", + "serif": "Serif", + "sans-serif": "Sans Serif", + "monospace": "Aonspás", + "system-default": "Réamhshocrú an chórais" + }, + "max_content_width": { + "title": "Leithead an Ábhair", + "default_description": "De réir réamhshocraithe, cuireann Trilium teorainn le huasleithead an ábhair chun inléiteacht a fheabhsú le haghaidh scáileáin uasmhéadaithe ar scáileáin leathana.", + "max_width_label": "Leithead uasta an ábhair", + "max_width_unit": "picteilíní", + "centerContent": "Coinnigh an t-ábhar i lár an aonaigh" + }, + "native_title_bar": { + "title": "Barra Teidil Dúchasach (éilíonn atosú an aip)", + "enabled": "cumasaithe", + "disabled": "díchumasaithe" + }, + "ribbon": { + "widgets": "Giuirléidí ribín", + "promoted_attributes_message": "Osclófar an cluaisín ribín Tréithe Ardaithe go huathoibríoch má tá tréithe ardaithe i láthair ar an nóta", + "edited_notes_message": "Osclófar an cluaisín ribín Nótaí Eagarthóireachta go huathoibríoch ar nótaí lae" + }, + "theme": { + "title": "Téama an Iarratais", + "theme_label": "Téama", + "override_theme_fonts_label": "Sáraigh clónna téama", + "auto_theme": "Seanchóras (Lean scéim dathanna an chórais)", + "light_theme": "Oidhreacht (Éadrom)", + "dark_theme": "Oidhreacht (Dorcha)", + "triliumnext": "Trilium (Lean scéim dathanna an chórais)", + "triliumnext-light": "Trilium (Éadrom)", + "triliumnext-dark": "Trilium (Dorcha)", + "layout": "Leagan Amach", + "layout-vertical-title": "Ingearach", + "layout-horizontal-title": "Cothrománach", + "layout-vertical-description": "tá barra lainseála ar chlé (réamhshocraithe)", + "layout-horizontal-description": "Tá barra an lainseálaí faoin mbarra cluaisín, tá an barra cluaisín lánleithead anois." + }, + "ui-performance": { + "title": "Feidhmíocht", + "enable-motion": "Cumasaigh aistrithe agus beochana", + "enable-shadows": "Cumasaigh scáthanna", + "enable-backdrop-effects": "Cumasaigh éifeachtaí cúlra do bhiachláir, fuinneoga aníos agus painéil", + "enable-smooth-scroll": "Cumasaigh scrollú réidh", + "app-restart-required": "(tá atosú an fheidhmchláir ag teastáil chun an t-athrú a chur i bhfeidhm)" + }, + "ai_llm": { + "not_started": "Níor tosaíodh", + "title": "Socruithe AI", + "processed_notes": "Nótaí Próiseáilte", + "total_notes": "Nótaí Iomlána", + "progress": "Dul Chun Cinn", + "queued_notes": "Nótaí i gCiú", + "failed_notes": "Nótaí Theipthe", + "last_processed": "Próiseáilte Deiridh", + "refresh_stats": "Athnuachan Staitisticí", + "enable_ai_features": "Cumasaigh gnéithe AI/LLM", + "enable_ai_description": "Cumasaigh gnéithe AI cosúil le achoimre nótaí, giniúint ábhair, agus cumais LLM eile", + "openai_tab": "OpenAI", + "anthropic_tab": "Anthropic", + "voyage_tab": "Voyage AI", + "ollama_tab": "Ollama", + "enable_ai": "Cumasaigh gnéithe AI/LLM", + "enable_ai_desc": "Cumasaigh gnéithe AI cosúil le achoimre nótaí, giniúint ábhair, agus cumais LLM eile", + "provider_configuration": "Cumraíocht Soláthraí AI", + "provider_precedence": "Tosaíocht Soláthraí", + "provider_precedence_description": "Liosta soláthraithe scartha le camóga in ord tosaíochta (m.sh., 'openai, anthropic, ollama')", + "temperature": "Teocht", + "temperature_description": "Rialaíonn randamacht i bhfreagraí (0 = cinntitheach, 2 = uasmhéid randamachta)", + "system_prompt": "Pras Córais", + "system_prompt_description": "Leid réamhshocraithe an chórais a úsáidtear le haghaidh gach idirghníomhaíocht AI", + "openai_configuration": "Cumraíocht OpenAI", + "openai_settings": "Socruithe OpenAI", + "api_key": "Eochair API", + "url": "Bun-URL", + "model": "Samhail", + "openai_api_key_description": "D'eochair API OpenAI chun rochtain a fháil ar a gcuid seirbhísí AI", + "anthropic_api_key_description": "D'eochair API Anthropic chun rochtain a fháil ar mhúnlaí Claude", + "default_model": "Samhail Réamhshocraithe", + "openai_model_description": "Samplaí: gpt-4o, gpt-4-turbo, gpt-3.5-turbo", + "base_url": "Bun-URL", + "openai_url_description": "Réamhshocrú: https://api.openai.com/v1", + "anthropic_settings": "Socruithe Anthropic", + "anthropic_url_description": "Bun-URL don Anthropic API (réamhshocraithe: https://api.anthropic.com)", + "anthropic_model_description": "Samhlacha Anthropic Claude le haghaidh comhlánú comhrá", + "voyage_settings": "Socruithe Voyage AI", + "ollama_settings": "Socruithe Ollama", + "ollama_url_description": "URL don Ollama API (réamhshocrú: http://localhost:11434)", + "ollama_model_description": "Samhail Ollama le húsáid le haghaidh comhrá a chríochnú", + "anthropic_configuration": "Cumraíocht Anthropic", + "voyage_configuration": "Cumraíocht AI Voyage", + "voyage_url_description": "Réamhshocrú: https://api.voyageai.com/v1", + "ollama_configuration": "Cumraíocht Ollama", + "enable_ollama": "Cumasaigh Ollama", + "enable_ollama_description": "Cumasaigh Ollama le haghaidh úsáide áitiúla samhail AI", + "ollama_url": "URL Ollama", + "ollama_model": "Samhail Ollama", + "refresh_models": "Athnuachan Samhlacha", + "refreshing_models": "Ag athnuachan...", + "enable_automatic_indexing": "Cumasaigh Innéacsú Uathoibríoch", + "rebuild_index": "Innéacs Athchóirithe", + "rebuild_index_error": "Earráid ag tosú atógáil an innéacs. Seiceáil na logaí le haghaidh sonraí.", + "note_title": "Teideal an Nóta", + "error": "Earráid", + "last_attempt": "Iarracht Dheiridh", + "actions": "Gníomhartha", + "retry": "Déan iarracht eile", + "partial": "{{ percentage }}% críochnaithe", + "retry_queued": "Nóta curtha i scuaine le haghaidh athiarrachta", + "retry_failed": "Theip ar an nóta a chur sa scuaine le haghaidh athiarrachta", + "max_notes_per_llm_query": "Uasmhéid Nótaí In Aghaidh an Fhiosrúcháin", + "max_notes_per_llm_query_description": "Uasmhéid nótaí comhchosúla le cur san áireamh i gcomhthéacs na hintleachta saorga", + "active_providers": "Soláthraithe Gníomhacha", + "disabled_providers": "Soláthraithe faoi Mhíchumas", + "remove_provider": "Bain an soláthraí as an gcuardach", + "restore_provider": "Athchóirigh soláthraí chuig an gcuardach", + "similarity_threshold": "Tairseach Cosúlachta", + "similarity_threshold_description": "Scór cosúlachta íosta (0-1) le go n-áireofar nótaí i gcomhthéacs fiosrúcháin LLM", + "reprocess_index": "Athchruthaigh Innéacs Cuardaigh", + "reprocessing_index": "Atógáil...", + "reprocess_index_started": "Cuireadh tús le hoptamú innéacs cuardaigh sa chúlra", + "reprocess_index_error": "Earráid ag atógáil innéacs cuardaigh", + "index_rebuild_progress": "Dul Chun Cinn Athchóirithe Innéacs", + "index_rebuilding": "Innéacs optamaithe ({{percentage}}%)", + "index_rebuild_complete": "Uasmhéadú innéacs críochnaithe", + "index_rebuild_status_error": "Earráid ag seiceáil stádas athchóirithe innéacs", + "never": "Choíche", + "processing": "Próiseáil ({{percentage}}%)", + "incomplete": "Neamhchríochnaithe ({{percentage}}%)", + "complete": "Críochnaithe (100%)", + "refreshing": "Ag athnuachan...", + "auto_refresh_notice": "Athnuachan uathoibríoch gach {{seconds}} soicind", + "note_queued_for_retry": "Nóta curtha i scuaine le haghaidh athiarrachta", + "failed_to_retry_note": "Theip ar an nóta a athdhéanamh", + "all_notes_queued_for_retry": "Gach nóta nár éirigh leo curtha i scuaine le haghaidh athiarrachta", + "failed_to_retry_all": "Theip ar athiarracht nótaí", + "ai_settings": "Socruithe AI", + "api_key_tooltip": "Eochair API chun rochtain a fháil ar an tseirbhís", + "empty_key_warning": { + "anthropic": "Tá eochair API Anthropic folamh. Cuir isteach eochair API bhailí le do thoil.", + "openai": "Tá eochair API OpenAI folamh. Cuir isteach eochair API bhailí le do thoil.", + "voyage": "Tá eochair API Voyage folamh. Cuir isteach eochair API bhailí le do thoil.", + "ollama": "Tá eochair API Ollama folamh. Cuir isteach eochair API bhailí le do thoil." + }, + "agent": { + "processing": "Ag próiseáil...", + "thinking": "Ag smaoineamh...", + "loading": "Ag lódáil...", + "generating": "Ag giniúint..." + }, + "name": "Intleacht Shaorga", + "openai": "OpenAI", + "use_enhanced_context": "Úsáid comhthéacs feabhsaithe", + "enhanced_context_description": "Tugann sé níos mó comhthéacs don AI ón nóta agus a nótaí gaolmhara le haghaidh freagraí níos fearr", + "show_thinking": "Taispeáin smaointeoireacht", + "show_thinking_description": "Taispeáin slabhra phróiseas smaointeoireachta na hintleachta saorga", + "enter_message": "Cuir isteach do theachtaireacht...", + "error_contacting_provider": "Earráid ag teacht i dteagmháil leis an soláthraí AI. Seiceáil do shocruithe agus do nasc idirlín le do thoil.", + "error_generating_response": "Earráid ag giniúint freagra AI", + "index_all_notes": "Innéacs na Nótaí Uile", + "index_status": "Stádas Innéacs", + "indexed_notes": "Nótaí Innéacsaithe", + "indexing_stopped": "Stopadh an innéacsú", + "indexing_in_progress": "Innéacsú ar siúl...", + "last_indexed": "Innéacsaithe Deiridh", + "note_chat": "Comhrá Nótaí", + "sources": "Foinsí", + "start_indexing": "Tosaigh ag Innéacsú", + "use_advanced_context": "Úsáid Comhthéacs Ardleibhéil", + "ollama_no_url": "Níl Ollama cumraithe. Cuir isteach URL bailí le do thoil.", + "chat": { + "root_note_title": "Comhráite AI", + "root_note_content": "Tá do chomhráite comhrá AI sábháilte sa nóta seo.", + "new_chat_title": "Comhrá Nua", + "create_new_ai_chat": "Cruthaigh Comhrá AI nua" + }, + "create_new_ai_chat": "Cruthaigh Comhrá AI nua", + "configuration_warnings": "Tá roinnt fadhbanna le do chumraíocht AI. Seiceáil do shocruithe le do thoil.", + "experimental_warning": "Tá an ghné LLM turgnamhach faoi láthair - tugadh rabhadh duit.", + "selected_provider": "Soláthraí Roghnaithe", + "selected_provider_description": "Roghnaigh an soláthraí AI le haghaidh gnéithe comhrá agus comhlánaithe", + "select_model": "Roghnaigh samhail...", + "select_provider": "Roghnaigh soláthraí...", + "ai_enabled": "Gnéithe AI cumasaithe", + "ai_disabled": "Gnéithe AI díchumasaithe", + "no_models_found_online": "Níor aimsíodh aon mhúnlaí. Seiceáil d’eochair API agus do shocruithe le do thoil.", + "no_models_found_ollama": "Níor aimsíodh aon mhúnlaí Ollama. Seiceáil le do thoil an bhfuil Ollama ag rith.", + "error_fetching": "Earráid ag fáil samhlacha: {{error}}" + }, + "zoom_factor": { + "title": "Fachtóir Súmáil (leagan deisce amháin)", + "description": "Is féidir súmáil a rialú le haicearraí CTRL+- agus CTRL+= chomh maith." + }, + "code_auto_read_only_size": { + "title": "Méid Uathoibríoch Léite Amháin", + "description": "Is é méid uathoibríoch nótaí inléite amháin an méid tar éis a dtaispeánfar nótaí i mód inléite amháin (ar chúiseanna feidhmíochta).", + "label": "Méid inléite amháin uathoibríoch (nótaí cóid)", + "unit": "carachtair" + }, + "code-editor-options": { + "title": "Eagarthóir" + }, + "code_mime_types": { + "title": "Cineálacha MIME atá ar fáil sa roghchlár anuas", + "tooltip_syntax_highlighting": "Aibhsiú comhréire", + "tooltip_code_block_syntax": "Bloic chóid i nótaí Téacs", + "tooltip_code_note_syntax": "Nótaí cóid" + }, + "vim_key_bindings": { + "use_vim_keybindings_in_code_notes": "Ceangail eochracha Vim", + "enable_vim_keybindings": "Cumasaigh ceangail eochracha Vim i nótaí cóid (gan mód ex)" + }, + "wrap_lines": { + "wrap_lines_in_code_notes": "Fill línte i nótaí cóid", + "enable_line_wrap": "Cumasaigh Fillteán Líne (b’fhéidir go mbeadh athlódáil tosaigh ag teastáil chun go dtiocfadh an t-athrú i bhfeidhm)" + }, + "images": { + "images_section_title": "Íomhánna", + "download_images_automatically": "Íoslódáil íomhánna go huathoibríoch le húsáid as líne.", + "download_images_description": "Is féidir tagairtí d’íomhánna ar líne a bheith i HTML greamaithe, aimseoidh Trilium na tagairtí sin agus íoslódálfaidh sé na híomhánna ionas go mbeidh siad ar fáil as líne.", + "enable_image_compression": "Cumasaigh comhbhrú íomhá", + "max_image_dimensions": "Uasleithead/airde íomhá (athrófar méid na híomhá má sháraíonn sí an socrú seo).", + "max_image_dimensions_unit": "picteilíní", + "jpeg_quality_description": "Cáilíocht JPEG (10 - an caighdeán is measa, 100 - an caighdeán is fearr, moltar 50 - 85)" + }, + "attachment_erasure_timeout": { + "attachment_erasure_timeout": "Am Teorann Scriosadh Ceangaltáin", + "attachment_auto_deletion_description": "Scriostar ceangaltáin go huathoibríoch (agus scriostar iad) mura ndéantar tagairt dóibh ina nóta a thuilleadh tar éis tréimhse ama socraithe.", + "erase_attachments_after": "Scrios ceangaltáin neamhúsáidte tar éis:", + "manual_erasing_description": "Is féidir leat scriosadh a spreagadh de láimh freisin (gan an t-am críochnaithe a shainmhínítear thuas a chur san áireamh):", + "erase_unused_attachments_now": "Scrios nótaí ceangaltáin neamhúsáidte anois", + "unused_attachments_erased": "Scriosadh ceangaltáin neamhúsáidte." + }, + "network_connections": { + "network_connections_title": "Naisc Líonra", + "check_for_updates": "Seiceáil le haghaidh nuashonruithe go huathoibríoch" + }, + "note_erasure_timeout": { + "note_erasure_timeout_title": "Am Scriosadh Nótaí", + "note_erasure_description": "Ní dhéantar nótaí scriosta (agus tréithe, athbhreithnithe...) a mharcáil ach mar scriosta ar dtús agus is féidir iad a aisghabháil ón dialóg Nótaí Le Déanaí. Tar éis tamaill, déantar nótaí scriosta a \"scriosadh\" rud a chiallaíonn nach féidir a n-ábhar a aisghabháil a thuilleadh. Ligeann an socrú seo duit fad na tréimhse idir an nóta a scriosadh agus a scriosadh a chumrú.", + "erase_notes_after": "Scrios nótaí tar éis:", + "manual_erasing_description": "Is féidir leat scriosadh a spreagadh de láimh freisin (gan an t-am críochnaithe a shainmhínítear thuas a chur san áireamh):", + "erase_deleted_notes_now": "Scrios nótaí scriosta anois", + "deleted_notes_erased": "Tá nótaí scriosta scriosta." + }, + "revisions_snapshot_interval": { + "note_revisions_snapshot_interval_title": "Eatramh Léirmheasa ar Nóta", + "note_revisions_snapshot_description": "Is é an t-eatramh pictiúr athbhreithnithe nóta an t-am ina dhiaidh a chruthófar athbhreithniú nóta nua don nóta. Féach vicí le haghaidh tuilleadh eolais.", + "snapshot_time_interval_label": "Eatramh ama pictiúr athbhreithnithe nóta:" + }, + "revisions_snapshot_limit": { + "note_revisions_snapshot_limit_title": "Teorainn ar Ghrianghraf Athbhreithnithe Nóta", + "note_revisions_snapshot_limit_description": "Tagraíonn an teorainn ar líon na n-athbhreithnithe nótaí don líon uasta athbhreithnithe is féidir a shábháil do gach nóta. Ciallaíonn -1 gan aon teorainn, ciallaíonn 0 scriosadh na hathbhreithnithe go léir. Is féidir leat an líon uasta athbhreithnithe a shocrú do nóta aonair tríd an lipéad #versioningLimit.", + "snapshot_number_limit_label": "Teorainn líon na n-íomhánna athbhreithnithe nóta:", + "snapshot_number_limit_unit": "léargais", + "erase_excess_revision_snapshots": "Scrios na léargais athbhreithnithe breise anois", + "erase_excess_revision_snapshots_prompt": "Scriosadh na léargais bhreise athbhreithnithe." + }, + "search_engine": { + "title": "Inneall Cuardaigh", + "custom_search_engine_info": "Éilíonn inneall cuardaigh saincheaptha go socrófar ainm agus URL araon. Mura socraítear ceachtar acu seo, úsáidfear DuckDuckGo mar an t-inneall cuardaigh réamhshocraithe.", + "predefined_templates_label": "Teimpléid inneall cuardaigh réamhshainithe", + "bing": "Bing", + "baidu": "Baidu", + "duckduckgo": "DuckDuckGo", + "google": "Google", + "custom_name_label": "Ainm innill chuardaigh saincheaptha", + "custom_name_placeholder": "Saincheap ainm an innill chuardaigh", + "custom_url_label": "Ba chóir go mbeadh {keyword} san áireamh mar áitchoinneálaí don téarma cuardaigh i URL inneall cuardaigh saincheaptha.", + "custom_url_placeholder": "Saincheap url an innill chuardaigh", + "save_button": "Sábháil" + }, + "tray": { + "title": "Tráidire an Chórais", + "enable_tray": "Cumasaigh an tráidire (ní mór Trilium a atosú le go dtiocfaidh an t-athrú seo i bhfeidhm)" + }, + "heading_style": { + "title": "Stíl Ceannteidil", + "plain": "Simplí", + "underline": "Folínigh", + "markdown": "Stíl marcála síos" + }, + "highlights_list": { + "title": "Liosta Buaicphointí", + "description": "Is féidir leat an liosta buaicphointí a thaispeántar sa phainéal ar dheis a shaincheapadh:", + "bold": "Téacs trom", + "italic": "Téacs iodálach", + "underline": "Téacs faoi líne", + "color": "Téacs daite", + "bg_color": "Téacs le dath cúlra", + "visibility_title": "Infheictheacht an Liosta Buaicphointí", + "visibility_description": "Is féidir leat an giuirléid buaicphointí a cheilt in aghaidh an nóta trí lipéad #hideHighlightWidget a chur leis.", + "shortcut_info": "Is féidir leat aicearra méarchláir a chumrú chun an painéal ar dheis (lena n-áirítear Buaicphointí) a athrú go tapa sna Roghanna -> Aicearraí (ainm 'toggleRightPane')." + }, + "table_of_contents": { + "title": "Clár Ábhair", + "description": "Beidh clár ábhair le feiceáil i nótaí téacs nuair a bhíonn níos mó ná líon sainithe ceannteidil sa nóta. Is féidir leat an líon seo a shaincheapadh:", + "unit": "ceannteidil", + "disable_info": "Is féidir leat an rogha seo a úsáid freisin chun TOC a dhíchumasú go héifeachtach trí uimhir an-ard a shocrú.", + "shortcut_info": "Is féidir leat aicearra méarchláir a chumrú chun an painéal ar dheis (lena n-áirítear an tÁbhar Ábhar) a athrú go tapa sna Roghanna -> Aicearraí (ainm 'toggleRightPane')." + }, + "text_auto_read_only_size": { + "title": "Méid Uathoibríoch Léite Amháin", + "description": "Is é méid uathoibríoch nótaí inléite amháin an méid tar éis a dtaispeánfar nótaí i mód inléite amháin (ar chúiseanna feidhmíochta).", + "label": "Méid inléite amháin uathoibríoch (nótaí téacs)", + "unit": "carachtair" + }, + "custom_date_time_format": { + "title": "Formáid Dáta/Am Saincheaptha", + "description": "Saincheap formáid an dáta agus an ama a chuirtear isteach trí nó an barra uirlisí. Féach ar doiciméid Day.js le haghaidh na gcomharthaí formáide atá ar fáil.", + "format_string": "Formáid teaghrán:", + "formatted_time": "Dáta/am formáidithe:" + }, + "i18n": { + "title": "Logánú", + "language": "Teanga", + "first-day-of-the-week": "An chéad lá den tseachtain", + "monday": "Dé Luain", + "tuesday": "Dé Máirt", + "wednesday": "Dé Céadaoin", + "thursday": "Déardaoin", + "friday": "Dé hAoine", + "saturday": "Dé Sathairn", + "sunday": "Dé Domhnaigh", + "first-week-of-the-year": "An chéad seachtain den bhliain", + "first-week-contains-first-day": "Tá an chéad lá den bhliain sa chéad seachtain", + "first-week-contains-first-thursday": "Tá an chéad Déardaoin den bhliain sa chéad seachtain", + "first-week-has-minimum-days": "Tá an chéad seachtain ag an íosmhéid laethanta", + "min-days-in-first-week": "Íosmhéid laethanta sa chéad seachtain", + "first-week-info": "Tá an chéad seachtain ina bhfuil an chéad Déardaoin den bhliain bunaithe ar chaighdeán ISO 8601.", + "first-week-warning": "D’fhéadfadh sé go mbeadh dúblach le Nótaí Seachtaine atá ann cheana féin mar thoradh ar athrú roghanna na chéad seachtaine agus ní dhéanfar na Nótaí Seachtaine atá ann cheana a nuashonrú dá réir.", + "formatting-locale": "Formáid dáta agus uimhreach", + "formatting-locale-auto": "Bunaithe ar theanga an fheidhmchláir" + }, + "backup": { + "automatic_backup": "Cúltaca uathoibríoch", + "automatic_backup_description": "Is féidir le Trilium cúltaca den bhunachar sonraí a dhéanamh go huathoibríoch:", + "enable_daily_backup": "Cumasaigh cúltaca laethúil", + "enable_weekly_backup": "Cumasaigh cúltaca seachtainiúil", + "enable_monthly_backup": "Cumasaigh cúltaca míosúil", + "backup_recommendation": "Moltar an cúltaca a choinneáil casta air, ach is féidir leis seo moill a chur ar thosú feidhmchlár le bunachair shonraí móra agus/nó gléasanna stórála mall.", + "backup_now": "Cúltaca anois", + "backup_database_now": "Cúltaca bunachar sonraí anois", + "existing_backups": "Cúltacaí atá ann cheana féin", + "date-and-time": "Dáta & am", + "path": "Cosán", + "database_backed_up_to": "Tá cúltaca déanta den bhunachar sonraí chuig {{backupFilePath}}", + "no_backup_yet": "gan aon chúltaca fós" + }, + "etapi": { + "title": "ETAPI", + "description": "Is API REST é ETAPI a úsáidtear chun rochtain a fháil ar shampla Trilium go ríomhchláraitheach, gan chomhéadan úsáideora.", + "create_token": "Cruthaigh comhartha ETAPI nua", + "existing_tokens": "Comharthaí atá ann cheana féin", + "no_tokens_yet": "Níl aon chomharthaí ann fós. Cliceáil ar an gcnaipe thuas chun ceann a chruthú.", + "token_name": "Ainm an chomhartha", + "created": "Cruthaithe", + "actions": "Gníomhartha", + "new_token_title": "Comhartha ETAPI nua", + "new_token_message": "Cuir isteach ainm an chomhartha nua le do thoil", + "default_token_name": "comhartha nua", + "error_empty_name": "Ní féidir ainm an chomhartha a fhágáil folamh", + "token_created_title": "Cruthaíodh comhartha ETAPI", + "token_created_message": "Cóipeáil an comhartha cruthaithe isteach sa ghearrthaisce. Stórálann Trilium an comhartha haisithe agus seo an uair dheireanach a fheiceann tú é.", + "rename_token": "Athainmnigh an comhartha seo", + "delete_token": "Scrios / díghníomhachtaigh an comhartha seo", + "rename_token_title": "Athainmnigh an comhartha", + "rename_token_message": "Cuir isteach ainm an chomhartha nua le do thoil", + "delete_token_confirmation": "An bhfuil tú cinnte gur mian leat comhartha ETAPI \"{{name}}\" a scriosadh?" + }, + "options_widget": { + "options_status": "Stádas na roghanna", + "options_change_saved": "Tá na hathruithe roghanna sábháilte." + }, + "password": { + "heading": "Pasfhocal", + "alert_message": "Cuimhnigh ar do phasfhocal nua, le do thoil. Úsáidtear an pasfhocal chun logáil isteach sa chomhéadan gréasáin agus chun nótaí faoi chosaint a chriptiú. Má dhéanann tú dearmad ar do phasfhocal, cailltear do nótaí faoi chosaint go deo.", + "reset_link": "Cliceáil anseo chun é a athshocrú.", + "old_password": "Seanfhocal faire", + "new_password": "Pasfhocal nua", + "new_password_confirmation": "Deimhniú pasfhocail nua", + "change_password": "Athraigh an focal faire", + "protected_session_timeout": "Am Teorann Seisiúin Chosanta", + "protected_session_timeout_description": "Is tréimhse ama í an t-am scoir seisiúin chosanta a scriostar an seisiún cosanta ó chuimhne an bhrabhsálaí ina dhiaidh. Déantar é seo a thomhas ón idirghníomhaíocht dheireanach le nótaí cosanta. Féach", + "wiki": "vicí", + "for_more_info": "le haghaidh tuilleadh eolais.", + "protected_session_timeout_label": "Am scoir seisiúin faoi chosaint:", + "reset_confirmation": "Trí an focal faire a athshocrú caillfidh tú rochtain go deo ar do nótaí cosanta go léir atá ann cheana féin. An bhfuil tú cinnte gur mhaith leat an focal faire a athshocrú?", + "reset_success_message": "Athshocraíodh an focal faire. Socraigh focal faire nua le do thoil", + "change_password_heading": "Athraigh Pasfhocal", + "set_password_heading": "Socraigh Pasfhocal", + "set_password": "Socraigh Pasfhocal", + "password_mismatch": "Ní hionann pasfhocail nua.", + "password_changed_success": "Athraíodh an focal faire. Athlódálfar Trilium tar éis duit brúigh OK." + }, + "multi_factor_authentication": { + "title": "Fíordheimhniú Ilfhachtóireach", + "description": "Cuireann Fíordheimhniú Ilfhachtóireach (FFA) ciseal breise slándála le do chuntas. In ionad pasfhocal a iontráil le logáil isteach, éilíonn FFA ort píosa fianaise amháin nó níos mó a sholáthar chun d’aitheantas a fhíorú. Ar an mbealach seo, fiú má fhaigheann duine éigin do phasfhocal, ní féidir leo rochtain a fháil ar do chuntas gan an dara píosa faisnéise. Tá sé cosúil le glas breise a chur le do dhoras, rud a fhágann go bhfuil sé i bhfad níos deacra d’aon duine eile briseadh isteach.

Lean na treoracha thíos le do thoil chun FFA a chumasú. Mura ndéanann tú an chumraíocht i gceart, ní bheidh ach pasfhocal ag teastáil chun logáil isteach.", + "mfa_enabled": "Cumasaigh Fíordheimhniú Ilfhachtóireach", + "mfa_method": "Modh MFA", + "electron_disabled": "Ní thacaítear le Fíordheimhniú Ilfhachtóireach sa leagan deisce faoi láthair.", + "totp_title": "Pasfhocal Aonuaire Bunaithe ar Am (TOTP)", + "totp_description": "Is gné slándála é TOTP (Pasfhocal Aonuaire Bunaithe ar Am) a ghineann cód uathúil, sealadach a athraíonn gach 30 soicind. Úsáideann tú an cód seo, mar aon le do phasfhocal, chun logáil isteach i do chuntas, rud a fhágann go bhfuil sé i bhfad níos deacra d’aon duine eile rochtain a fháil air.", + "totp_secret_title": "Gin Rún TOTP", + "totp_secret_generate": "Gin Rún TOTP", + "totp_secret_regenerate": "Athghinigh Rún TOTP", + "no_totp_secret_warning": "Chun TOTP a chumasú, ní mór duit rún TOTP a ghiniúint ar dtús.", + "totp_secret_description_warning": "Tar éis rún TOTP nua a ghiniúint, beidh ort logáil isteach arís leis an rún TOTP nua.", + "totp_secret_generated": "Rún TOTP Gineadh", + "totp_secret_warning": "Sábháil an rún a gineadh in áit shábháilte. Ní thaispeánfar arís é.", + "totp_secret_regenerate_confirm": "An bhfuil tú cinnte gur mian leat an rún TOTP a athghiniúint? Cuirfidh sé seo an rún TOTP roimhe seo agus na cód aisghabhála atá ann cheana ar neamhní.", + "recovery_keys_title": "Eochracha Aisghabhála Síniúcháin Aonair", + "recovery_keys_description": "Úsáidtear eochracha aisghabhála sínithe isteach aonair chun logáil isteach fiú mura féidir leat rochtain a fháil ar do chóid Authenticator.", + "recovery_keys_description_warning": "Ní thaispeánfar eochracha aisghabhála arís tar éis duit an leathanach a fhágáil, coinnigh iad in áit shábháilte agus slán.
Ní féidir eochair aisghabhála a úsáid arís tar éis í a úsáid.", + "recovery_keys_error": "Earráid ag giniúint cóid aisghabhála", + "recovery_keys_no_key_set": "Níl aon chóid aisghabhála socraithe", + "recovery_keys_generate": "Gin Cóid Aisghabhála", + "recovery_keys_regenerate": "Athghinigh Cóid Aisghabhála", + "recovery_keys_used": "Úsáidte: {{date}}", + "recovery_keys_unused": "Níl an cód aisghabhála {{index}} in úsáid", + "oauth_title": "OAuth/OpenID", + "oauth_description": "Is bealach caighdeánaithe é OpenID a ligeann duit logáil isteach i suíomhanna gréasáin ag baint úsáide as cuntas ó sheirbhís eile, cosúil le Google, chun d’aitheantas a fhíorú. Is é Google an t-eisitheoir réamhshocraithe, ach is féidir leat é a athrú go haon soláthraí OpenID eile. Seiceáil anseo le haghaidh tuilleadh eolais. Lean na treoracha seo chun seirbhís OpenID a bhunú trí Google.", + "oauth_description_warning": "Chun OAuth/OpenID a chumasú, ní mór duit an URL bonn OAuth/OpenID, an ID cliaint agus an rún cliaint a shocrú sa chomhad config.ini agus an feidhmchlár a atosú. Más mian leat socruithe a dhéanamh ó athróga timpeallachta, socraigh TRILIUM_OAUTH_BASE_URL, TRILIUM_OAUTH_CLIENT_ID agus TRILIUM_OAUTH_CLIENT_SECRET le do thoil.", + "oauth_missing_vars": "Socruithe ar iarraidh: {{-variables}}", + "oauth_user_account": "Cuntas Úsáideora: ", + "oauth_user_email": "Ríomhphost an Úsáideora: ", + "oauth_user_not_logged_in": "Níl mé logáilte isteach!" + }, + "shortcuts": { + "keyboard_shortcuts": "Aicearraí Méarchláir", + "multiple_shortcuts": "Is féidir camóg a úsáid chun aicearraí iolracha don ghníomh céanna a dheighilt.", + "electron_documentation": "Féach ar dhoiciméadacht Electron le haghaidh modhnóirí agus cóid eochracha atá ar fáil.", + "type_text_to_filter": "Clóscríobh téacs chun aicearraí a scagadh...", + "action_name": "Ainm an ghnímh", + "shortcuts": "Aicearraí", + "default_shortcuts": "Aicearraí réamhshocraithe", + "description": "Cur síos", + "reload_app": "Athlódáil an aip chun na hathruithe a chur i bhfeidhm", + "set_all_to_default": "Socraigh gach aicearra go dtí an réamhshocrú", + "confirm_reset": "An bhfuil tú cinnte gur mhaith leat na haicearraí méarchláir go léir a athshocrú go dtí an rogha réamhshocraithe?", + "no_results": "Níor aimsíodh aon aicearraí a mheaitseálann '{{filter}}'" + }, + "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." + }, + "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).", + "special_value_description": "Luach speisialta eile is ea noproxy a chuireann iallach neamhaird a dhéanamh fiú ar an seachfhreastalaí córais agus a thugann meas ar NODE_TLS_REJECT_UNAUTHORIZED.", + "save": "Sábháil", + "help": "Cabhair", + "test_title": "Tástáil Sioncrónaithe", + "test_description": "Déanfaidh sé seo tástáil ar an nasc agus ar an gcroitheadh láimhe leis an bhfreastalaí sioncrónaithe. Mura bhfuil an freastalaí sioncrónaithe tosaithe, socróidh sé seo é chun sioncrónú leis an doiciméad áitiúil.", + "test_button": "Tástáil sioncrónaithe", + "handshake_failed": "Theip ar chroitheadh láimhe an fhreastalaí sioncrónaithe, earráid: {{message}}" + }, + "api_log": { + "close": "Dún" + }, + "attachment_detail_2": { + "will_be_deleted_in": "Scriosfar an ceangaltán seo go huathoibríoch i gceann {{time}}", + "will_be_deleted_soon": "Scriosfar an ceangaltán seo go huathoibríoch go luath", + "deletion_reason": ", mar nach bhfuil an ceangaltán nasctha in ábhar an nóta. Chun scriosadh a chosc, cuir an nasc ceangaltáin ar ais san ábhar nó tiontaigh an ceangaltán ina nóta.", + "role_and_size": "Ról: {{role}}, méid: {{size}}, MIME: {{- mimeType}}", + "link_copied": "Nasc an cheangail cóipeáilte chuig an ghearrthaisce.", + "unrecognized_role": "Ról ceangail neamhaitheanta '{{role}}'." + }, + "bookmark_switch": { + "bookmark": "Leabharmharc", + "bookmark_this_note": "Cuir an nóta seo i leabharmharcanna ar an bpainéal taobh clé", + "remove_bookmark": "Bain leabharmharc" + }, + "editability_select": { + "auto": "Uathoibríoch", + "read_only": "Léamh amháin", + "always_editable": "In-eagarthóireacht i gcónaí", + "note_is_editable": "Is féidir nóta a chur in eagar mura bhfuil sé rófhada.", + "note_is_read_only": "Is nóta inléite amháin é, ach is féidir é a chur in eagar le cliceáil cnaipe.", + "note_is_always_editable": "Is féidir nóta a chur in eagar i gcónaí, beag beann ar a fhad." + }, + "note-map": { + "button-link-map": "Léarscáil Nasc", + "button-tree-map": "Léarscáil crann" + }, + "tree-context-menu": { + "open-in-a-new-tab": "Oscail i gcluaisín nua", + "open-in-a-new-split": "Oscail i scoilt nua", + "open-in-a-new-window": "Oscail i bhfuinneog nua", + "insert-note-after": "Cuir nóta isteach ina dhiaidh", + "insert-child-note": "Cuir nóta linbh isteach", + "archive": "Cartlann", + "unarchive": "Díchartlannaigh", + "delete": "Scrios", + "search-in-subtree": "Cuardaigh i bhfo-chrann", + "hoist-note": "Nóta ardaitheora", + "unhoist-note": "Nóta dí-ardaithe", + "edit-branch-prefix": "Cuir réimír na brainse in eagar", + "advanced": "Ardleibhéil", + "expand-subtree": "Leathnaigh an fo-chrann", + "collapse-subtree": "Laghdaigh fo-chrann", + "hide-subtree": "Folaigh fo-chrann", + "show-subtree": "Taispeáin fo-chrann", + "sort-by": "Sórtáil de réir...", + "recent-changes-in-subtree": "Athruithe le déanaí sa fho-chrann", + "convert-to-attachment": "Tiontaigh go ceangaltán", + "copy-note-path-to-clipboard": "Cóipeáil cosán an nóta chuig an ghearrthaisce", + "protect-subtree": "Fo-chrann a chosaint", + "unprotect-subtree": "Díchosaint fochrann", + "copy-clone": "Cóipeáil / clónáil", + "clone-to": "Clónáil go...", + "cut": "Gearr", + "move-to": "Bog go...", + "paste-into": "Greamaigh isteach", + "paste-after": "Greamaigh ina dhiaidh", + "duplicate": "Dúblach", + "export": "Easpórtáil", + "import-into-note": "Iompórtáil isteach i nóta", + "apply-bulk-actions": "Cuir gníomhartha mórchóir i bhfeidhm", + "converted-to-attachments": "Tá {{count}} nótaí tiontaithe ina gceangaltáin.", + "convert-to-attachment-confirm": "An bhfuil tú cinnte gur mian leat na nótaí roghnaithe a thiontú ina gceangaltáin dá nótaí tuismitheora? Ní bhaineann an oibríocht seo ach le nótaí Íomhá, scipeálfar nótaí eile.", + "open-in-popup": "Eagarthóireacht thapa" + }, + "shared_info": { + "shared_publicly": "Tá an nóta seo roinnte go poiblí ar {{- link}}.", + "shared_locally": "Tá an nóta seo roinnte go háitiúil ar {{- link}}.", + "help_link": "Chun cabhair a fháil, tabhair cuairt ar wiki." + }, + "read-only-info": { + "read-only-note": "Ag féachaint ar nóta inléite amháin faoi láthair.", + "auto-read-only-note": "Taispeántar an nóta seo i mód léite amháin le haghaidh luchtú níos tapúla.", + "edit-note": "Cuir nóta in eagar" + }, + "note_types": { + "text": "Téacs", + "code": "Code", + "saved-search": "Cuardach Sábháilte", + "relation-map": "Léarscáil Gaolmhaireachta", + "note-map": "Léarscáil Nótaí", + "render-note": "Nóta Rindreála", + "book": "Bailiúchán", + "mermaid-diagram": "Léaráid Maighdeann Mhara", + "canvas": "Canbhás", + "web-view": "Radharc Gréasáin", + "mind-map": "Léarscáil Intinne", + "file": "Comhad", + "image": "Íomhá", + "launcher": "Tosaitheoir", + "doc": "Doiciméad", + "widget": "Giuirléid", + "confirm-change": "Ní mholtar cineál nóta a athrú nuair nach bhfuil ábhar an nóta folamh. Ar mhaith leat leanúint ar aghaidh ar aon nós?", + "geo-map": "Léarscáil Gheografach", + "beta-feature": "Béite", + "ai-chat": "Comhrá AI", + "task-list": "Liosta Tascanna", + "new-feature": "Nua", + "collections": "Bailiúcháin" + }, + "protect_note": { + "toggle-on": "Cosain an nóta", + "toggle-off": "Díchosaint an nóta", + "toggle-on-hint": "Níl an nóta cosanta, cliceáil chun é a chosaint", + "toggle-off-hint": "Tá an nóta cosanta, cliceáil chun é a dhéanamh neamhchosanta" + }, + "shared_switch": { + "shared": "Roinnte", + "toggle-on-title": "Roinn an nóta", + "toggle-off-title": "Díroinn an nóta", + "shared-branch": "Níl an nóta seo ann ach mar nóta comhroinnte, scriosfar é má dhíroinntear é. Ar mhaith leat leanúint ar aghaidh agus an nóta seo a scriosadh dá bharr?", + "inherited": "Ní féidir an nóta a dhíroinnt anseo mar go roinntear é trí oidhreacht ó shinsear." + }, + "template_switch": { + "template": "Teimpléad", + "toggle-on-hint": "Déan teimpléad den nóta", + "toggle-off-hint": "Bain an nóta mar theimpléad" + }, + "open-help-page": "Oscail leathanach cabhrach", + "find": { + "case_sensitive": "Cás-íogair", + "match_words": "Meaitseáil focail", + "find_placeholder": "Aimsigh sa téacs...", + "replace_placeholder": "Cuir in ionad le...", + "replace": "Athsholáthair", + "replace_all": "Cuir gach rud in ionad" + }, + "highlights_list_2": { + "title": "Liosta Buaicphointí", + "title_with_count_one": "{{count}} buaicphointe", + "title_with_count_two": "{{count}} buaicphointí", + "title_with_count_few": "{{count}} buaicphointí", + "title_with_count_many": "{{count}} buaicphointí", + "title_with_count_other": "{{count}} buaicphointí", + "options": "Roghanna", + "modal_title": "Cumraigh Liosta Buaicphointí", + "menu_configure": "Cumraigh liosta buaicphointí...", + "no_highlights": "Níor aimsíodh aon bhuaicphointí." + }, + "quick-search": { + "placeholder": "Cuardach tapa", + "searching": "Ag cuardach...", + "no-results": "Níor aimsíodh aon torthaí", + "more-results": "... agus {{number}} torthaí eile.", + "show-in-full-search": "Taispeáin sa chuardach iomlán" + }, + "note_tree": { + "collapse-title": "Laghdaigh crann nótaí", + "scroll-active-title": "Scrollaigh go dtí an nóta gníomhach", + "tree-settings-title": "Socruithe crann", + "hide-archived-notes": "Folaigh nótaí cartlannaithe", + "automatically-collapse-notes": "Nótaí a dhúnadh go huathoibríoch", + "automatically-collapse-notes-title": "Déanfar nótaí a dhúnadh tar éis tréimhse neamhghníomhaíochta chun an crann a dhí-phlódú.", + "save-changes": "Sábháil agus cuir athruithe i bhfeidhm", + "auto-collapsing-notes-after-inactivity": "Nótaí á gcúlú go huathoibríoch tar éis neamhghníomhaíochta...", + "saved-search-note-refreshed": "Nóta cuardaigh sábháilte athnuachan.", + "hoist-this-note-workspace": "Tóg an nóta seo (spás oibre)", + "refresh-saved-search-results": "Athnuaigh torthaí cuardaigh sábháilte", + "create-child-note": "Cruthaigh nóta linbh", + "unhoist": "Dí-ardaigh", + "toggle-sidebar": "Scoránaigh an taobhbharra", + "dropping-not-allowed": "Ní cheadaítear nótaí a fhágáil sa suíomh seo.", + "clone-indicator-tooltip": "Tá {{- count}} tuismitheoir ag an nóta seo: {{- parents}}", + "clone-indicator-tooltip-single": "Tá an nóta seo clónáilte (1 tuismitheoir breise: {{- parent}})", + "shared-indicator-tooltip": "Tá an nóta seo roinnte go poiblí", + "shared-indicator-tooltip-with-url": "Tá an nóta seo roinnte go poiblí ag: {{- url}}", + "subtree-hidden-tooltip_one": "{{count}} nóta linbh atá i bhfolach ón gcrann", + "subtree-hidden-tooltip_two": "{{count}} nótaí linbh atá i bhfolach ón gcrann", + "subtree-hidden-tooltip_few": "{{count}} nótaí linbh atá i bhfolach ón gcrann", + "subtree-hidden-tooltip_many": "{{count}} nótaí linbh atá i bhfolach ón gcrann", + "subtree-hidden-tooltip_other": "{{count}} nótaí linbh atá i bhfolach ón gcrann", + "subtree-hidden-moved-title": "Curtha le {{title}}", + "subtree-hidden-moved-description-collection": "Cuireann an bailiúchán seo a nótaí faoi bhun an tsean-nótaí i bhfolach sa chrann.", + "subtree-hidden-moved-description-other": "Tá nótaí linbh i bhfolach sa chrann don nóta seo." + }, + "title_bar_buttons": { + "window-on-top": "Coinnigh an Fhuinneog ar a Bharr" + }, + "note_detail": { + "could_not_find_typewidget": "Níorbh fhéidir typeWidget a aimsiú don chineál '{{type}}'", + "printing": "Priontáil ar siúl...", + "printing_pdf": "Ag easpórtáil go PDF ar siúl...", + "print_report_title": "Tuarascáil a phriontáil", + "print_report_collection_content_one": "Níorbh fhéidir nóta {{count}} sa bhailiúchán a phriontáil mar nach dtacaítear leo nó mar go bhfuil siad faoi chosaint.", + "print_report_collection_content_two": "Níorbh fhéidir {{count}} nótaí sa bhailiúchán a phriontáil mar nach dtacaítear leo nó mar go bhfuil siad faoi chosaint.", + "print_report_collection_content_few": "Níorbh fhéidir {{count}} nótaí sa bhailiúchán a phriontáil mar nach dtacaítear leo nó mar go bhfuil siad faoi chosaint.", + "print_report_collection_content_many": "Níorbh fhéidir {{count}} nótaí sa bhailiúchán a phriontáil mar nach dtacaítear leo nó mar go bhfuil siad faoi chosaint.", + "print_report_collection_content_other": "Níorbh fhéidir {{count}} nótaí sa bhailiúchán a phriontáil mar nach dtacaítear leo nó mar go bhfuil siad faoi chosaint.", + "print_report_collection_details_button": "Féach sonraí", + "print_report_collection_details_ignored_notes": "Nótaí neamhairdithe", + "print_report_error_title": "Theip ar phriontáil", + "print_report_stack_trace": "Rian cruachta" + }, + "note_title": { + "placeholder": "clóscríobh teideal an nóta anseo...", + "created_on": "Cruthaithe ar ", + "last_modified": "Modhnaithe ar ", + "note_type_switcher_label": "Athraigh ó {{type}} go:", + "note_type_switcher_others": "Cineál nóta eile", + "note_type_switcher_templates": "Teimpléad", + "note_type_switcher_collection": "Bailiúchán", + "edited_notes": "Nótaí curtha in eagar ar an lá seo", + "promoted_attributes": "Tréithe curtha chun cinn" + }, + "search_result": { + "no_notes_found": "Ní bhfuarthas aon nótaí do na paraiméadair chuardaigh tugtha.", + "search_not_executed": "Níl an cuardach curtha i gcrích fós. Cliceáil ar an gcnaipe \"Cuardaigh\" thuas chun na torthaí a fheiceáil." + }, + "spacer": { + "configure_launchbar": "Cumraigh an Barra Seoladh" + }, + "sql_result": { + "not_executed": "Níl an fiosrúchán curtha i gcrích fós.", + "no_rows": "Níl aon rónna curtha ar ais don fhiosrúchán seo", + "failed": "Theip ar fhorghníomhú an fhiosrúcháin SQL", + "statement_result": "Toradh ráitis", + "execute_now": "Rith anois" + }, + "sql_table_schemas": { + "tables": "Táblaí" + }, + "tab_row": { + "close_tab": "Dún an cluaisín", + "add_new_tab": "Cuir cluaisín nua leis", + "close": "Dún", + "close_other_tabs": "Dún cluaisíní eile", + "close_right_tabs": "Dún na cluaisíní ar dheis", + "close_all_tabs": "Dún gach cluaisín", + "reopen_last_tab": "Athoscail an cluaisín deireanach a dúnadh", + "move_tab_to_new_window": "Bog an cluaisín seo go fuinneog nua", + "copy_tab_to_new_window": "Cóipeáil an cluaisín seo chuig fuinneog nua", + "new_tab": "Cluaisín nua" + }, + "toc": { + "table_of_contents": "Clár Ábhair", + "options": "Roghanna", + "no_headings": "Gan ceannteidil." + }, + "watched_file_update_status": { + "file_last_modified": "Rinneadh an comhad a mhodhnú go deireanach ar .", + "upload_modified_file": "Uaslódáil comhad modhnaithe", + "ignore_this_change": "Déan neamhaird den athrú seo" + }, + "app_context": { + "please_wait_for_save": "Fan cúpla soicind le go mbeidh an sábháil críochnaithe, ansin is féidir leat iarracht eile a dhéanamh." + }, + "note_create": { + "duplicated": "Nóta: Tá \"{{title}}\" dúblaithe." + }, + "image": { + "copied-to-clipboard": "Tá tagairt don íomhá cóipeáilte chuig an ghearrthaisce. Is féidir é seo a ghreamú in aon nóta téacs.", + "cannot-copy": "Níorbh fhéidir tagairt na híomhá a chóipeáil chuig an ghearrthaisce." + }, + "clipboard": { + "cut": "Gearradh nóta(í) isteach sa ghearrthaisce.", + "copied": "Tá nóta(í) cóipeáilte isteach sa ghearrthaisce.", + "copy_failed": "Ní féidir cóipeáil chuig an ghearrthaisce mar gheall ar fhadhbanna ceadanna.", + "copy_success": "Cóipeáilte chuig an ghearrthaisce." + }, + "entrypoints": { + "note-revision-created": "Cruthaíodh athbhreithniú nóta.", + "note-executed": "Nóta curtha i gcrích.", + "sql-error": "Tharla earráid agus fiosrúchán SQL á fhorghníomhú: {{message}}" + }, + "branches": { + "cannot-move-notes-here": "Ní féidir nótaí a bhogadh anseo.", + "delete-status": "Stádas scriosta", + "delete-notes-in-progress": "Scrios nótaí atá ar siúl: {{count}}", + "delete-finished-successfully": "Scriosadh críochnaithe go rathúil.", + "undeleting-notes-in-progress": "Nótaí á n-athscriosadh ar siúl: {{count}}", + "undeleting-notes-finished-successfully": "Críochnaíodh athscriosadh na nótaí go rathúil." + }, + "frontend_script_api": { + "async_warning": "Tá feidhm neamhshioncrónach á cur agat chuig `api.runOnBackend()` agus is dócha nach n-oibreoidh sé mar a bhí beartaithe agat.\\nDéan an fheidhm sioncrónach (trí an eochairfhocal `async` a bhaint), nó bain úsáid as `api.runAsyncOnBackendWithManualTransactionHandling()`.", + "sync_warning": "Tá feidhm shioncrónach á cur agat chuig `api.runAsyncOnBackendWithManualTransactionHandling()`,\\n ach is dócha gur cheart duit `api.runOnBackend()` a úsáid ina ionad." + }, + "ws": { + "sync-check-failed": "Theip ar an seiceáil sioncrónaithe!", + "consistency-checks-failed": "Theip ar na seiceálacha comhsheasmhachta! Féach ar na logaí le haghaidh sonraí.", + "encountered-error": "Tharla earráid \"{{message}}\", féach ar an gconsól.", + "lost-websocket-connection-title": "Cailleadh an nasc leis an bhfreastalaí", + "lost-websocket-connection-message": "Seiceáil cumraíocht do sheachfhreastalaí droim ar ais (m.sh. nginx nó Apache) chun a chinntiú go bhfuil cead ceart ag naisc WebSocket agus nach bhfuil siad á mbac." + }, + "hoisted_note": { + "confirm_unhoisting": "Tá an nóta iarrtha '{{requestedNote}}' lasmuigh de fhochrann an nóta ardaithe '{{hoistedNote}}' agus ní mór duit é a dhí-ardú chun rochtain a fháil ar an nóta. Ar mhaith leat dul ar aghaidh leis an dí-ardú?" + }, + "launcher_context_menu": { + "reset_launcher_confirm": "An bhfuil tú cinnte gur mhaith leat \"{{title}}\" a athshocrú? Caillfear na sonraí/socruithe go léir sa nóta seo (agus a chlann) agus cuirfear an lainseálaí ar ais ina shuíomh bunaidh.", + "add-note-launcher": "Cuir lainseálaí nótaí leis", + "add-script-launcher": "Cuir lainseálaí scripte leis", + "add-custom-widget": "Cuir giuirléid saincheaptha leis", + "add-spacer": "Cuir spásaire leis", + "delete": "Scrios ", + "reset": "Athshocraigh", + "move-to-visible-launchers": "Bog chuig lainseálaithe infheicthe", + "move-to-available-launchers": "Bog chuig lainseálaithe atá ar fáil", + "duplicate-launcher": "Lainseálaí dúblach " + }, + "highlighting": { + "title": "Bloic Chóid", + "description": "Rialaíonn sé seo an aibhsiú comhréire do bhloic chód laistigh de nótaí téacs, ní bheidh tionchar aige seo ar nótaí cóid.", + "color-scheme": "Scéim Dathanna" + }, + "code_block": { + "word_wrapping": "Timfhilleadh focal", + "theme_none": "Gan aon aibhsiú comhréire", + "theme_group_light": "Téamaí éadroma", + "theme_group_dark": "Téamaí dorcha", + "copy_title": "Cóipeáil chuig an ghearrthaisce" + }, + "classic_editor_toolbar": { + "title": "Formáidiú" + }, + "editor": { + "title": "Eagarthóir" + }, + "editing": { + "editor_type": { + "label": "Barra uirlisí formáidithe", + "floating": { + "title": "Ar snámh", + "description": "feictear uirlisí eagarthóireachta in aice leis an gcúrsóir;" + }, + "fixed": { + "title": "Seasta", + "description": "Feictear uirlisí eagarthóireachta sa chluaisín ribín \"Formáidiú\"." + }, + "multiline-toolbar": "Taispeáin an barra uirlisí ar illínte mura n-oireann sé." + } + }, + "electron_context_menu": { + "add-term-to-dictionary": "Cuir \"{{term}}\" leis an bhfoclóir", + "cut": "Gearr", + "copy": "Cóipeáil", + "copy-link": "Cóipeáil nasc", + "paste": "Greamaigh", + "paste-as-plain-text": "Greamaigh mar théacs simplí", + "search_in_trilium": "Cuardaigh \"{{term}}\" i Trilium", + "search_online": "Cuardaigh \"{{term}}\" le {{search Engine}}" + }, + "image_context_menu": { + "copy_reference_to_clipboard": "Cóipeáil tagairt chuig an ghearrthaisce", + "copy_image_to_clipboard": "Cóipeáil íomhá chuig an ghearrthaisce" + }, + "link_context_menu": { + "open_note_in_new_tab": "Oscail nóta i gcluaisín nua", + "open_note_in_new_split": "Oscail nóta i scoilt nua", + "open_note_in_other_split": "Nóta oscailte sa scoilt eile", + "open_note_in_new_window": "Oscail nóta i bhfuinneog nua", + "open_note_in_popup": "Eagarthóireacht thapa" + }, + "electron_integration": { + "desktop-application": "Feidhmchlár Deisce", + "native-title-bar": "Barra teidil dúchasach", + "native-title-bar-description": "I gcás Windows agus macOS, má choinnítear an barra teidil dúchasach múchta, bíonn cuma níos dlúithe ar an bhfeidhmchlár. Ar Linux, má choinnítear an barra teidil dúchasach air, comhtháthaítear é níos fearr leis an gcuid eile den chóras.", + "background-effects": "Cumasaigh éifeachtaí cúlra", + "background-effects-description": "Cuireann sé cúlra doiléir, stíleach le fuinneoga aipeanna, rud a chruthaíonn doimhneacht agus cuma nua-aimseartha. Ní mór \"Barra teidil dúchasach\" a dhíchumasú.", + "restart-app-button": "Atosaigh an feidhmchlár chun na hathruithe a fheiceáil", + "zoom-factor": "Fachtóir súmála" + }, + "note_autocomplete": { + "search-for": "Cuardaigh \"{{term}}\"", + "create-note": "Cruthaigh agus nasc nóta linbh \"{{term}}\"", + "insert-external-link": "Cuir nasc seachtrach chuig \"{{term}}\" isteach", + "clear-text-field": "Glan réimse téacs", + "show-recent-notes": "Taispeáin nótaí le déanaí", + "full-text-search": "Cuardach téacs iomlán" + }, + "note_tooltip": { + "note-has-been-deleted": "Scriosadh an nóta.", + "quick-edit": "Eagarthóireacht thapa" + }, + "geo-map": { + "create-child-note-title": "Cruthaigh nóta nua do pháistí agus cuir leis an léarscáil é", + "create-child-note-text": "Cuir marcóir leis", + "create-child-note-instruction": "Cliceáil ar an léarscáil chun nóta nua a chruthú ag an suíomh sin nó brúigh Escape chun é a dhíbhe.", + "unable-to-load-map": "Ní féidir an léarscáil a luchtú." + }, + "geo-map-context": { + "open-location": "Oscail suíomh", + "remove-from-map": "Bain den léarscáil", + "add-note": "Cuir marcóir leis an suíomh seo" + }, + "help-button": { + "title": "Oscail an leathanach cabhrach ábhartha" + }, + "duration": { + "seconds": "Soicindí", + "minutes": "Nóiméid", + "hours": "Uaireanta", + "days": "Laethanta" + }, + "share": { + "title": "Socruithe Comhroinnte", + "redirect_bare_domain": "Atreoraigh fearann lom chuig an leathanach Comhroinnte", + "redirect_bare_domain_description": "Atreoraigh úsáideoirí gan ainm chuig an leathanach Comhroinnte in ionad Logáil Isteach a thaispeáint", + "show_login_link": "Taispeáin nasc Logála Isteach sa téama Comhroinnte", + "show_login_link_description": "Cuir nasc logála isteach le bunús an leathanaigh Chomhroinnte", + "check_share_root": "Seiceáil Stádas Fréamh Comhroinnte", + "share_root_found": "Tá an nóta fréimhe '{{noteTitle}}' réidh le roinnt", + "share_root_not_found": "Níor aimsíodh aon nóta leis an lipéad #shareRoot", + "share_root_not_shared": "Tá lipéad #shareRoot ag an nóta '{{noteTitle}}' ach níl sé roinnte" + }, + "time_selector": { + "invalid_input": "Ní uimhir bhailí an luach ama a iontráladh.", + "minimum_input": "Ní mór don luach ama a iontráladh a bheith {{minimumSeconds}} soicind ar a laghad." + }, + "tasks": { + "due": { + "today": "Inniu", + "tomorrow": "Amárach", + "yesterday": "Inné" + } + }, + "content_widget": { + "unknown_widget": "Giuirléid anaithnid do \"{{id}}\"." + }, + "note_language": { + "not_set": "Gan aon teanga socraithe", + "configure-languages": "Cumraigh teangacha...", + "help-on-languages": "Cabhair le teangacha ábhair..." + }, + "content_language": { + "title": "Teangacha ábhair", + "description": "Roghnaigh teanga amháin nó níos mó ar cheart dóibh a bheith le feiceáil sa rogha teanga sa rannán Airíonna Bunúsacha de nóta téacs inléite amháin nó in-eagarthóireachta. Ceadóidh sé seo gnéithe ar nós seiceáil litrithe nó tacaíocht ó dheis go clé." + }, + "switch_layout_button": { + "title_vertical": "Bog an painéal eagarthóireachta go dtí an bun", + "title_horizontal": "Bog an painéal eagarthóireachta ar chlé" + }, + "toggle_read_only_button": { + "unlock-editing": "Díghlasáil eagarthóireacht", + "lock-editing": "Eagarthóireacht glasála" + }, + "png_export_button": { + "button_title": "Easpórtáil léaráid mar PNG" + }, + "svg": { + "export_to_png": "Níorbh fhéidir an léaráid a easpórtáil go PNG.", + "export_to_svg": "Níorbh fhéidir an léaráid a easpórtáil chuig SVG." + }, + "code_theme": { + "title": "Dealramh", + "word_wrapping": "Timfhilleadh focal", + "color-scheme": "Scéim dathanna" + }, + "cpu_arch_warning": { + "title": "Íoslódáil leagan ARM64 le do thoil", + "message_macos": "Tá TriliumNext ag rith faoi aistriúchán Rosetta 2 faoi láthair, rud a chiallaíonn go bhfuil an leagan Intel (x64) á úsáid agat ar Apple Silicon Mac. Beidh tionchar suntasach aige seo ar fheidhmíocht agus ar shaolré na ceallraí.", + "message_windows": "Tá aithris á rith ag TriliumNext faoi láthair, rud a chiallaíonn go bhfuil an leagan Intel (x64) á úsáid agat ar ghléas Windows ar ARM. Beidh tionchar suntasach aige seo ar fheidhmíocht agus ar shaolré na ceallraí.", + "recommendation": "Chun an taithí is fearr a fháil, íoslódáil an leagan dúchasach ARM64 de TriliumNext ónár leathanach eisiúintí.", + "download_link": "Íoslódáil Leagan Dúchasach", + "continue_anyway": "Lean ar aghaidh ar aon nós", + "dont_show_again": "Ná taispeáin an rabhadh seo arís" + }, + "editorfeatures": { + "title": "Gnéithe", + "emoji_completion_enabled": "Cumasaigh uath-chomhlánú Emoji", + "emoji_completion_description": "Más cumasaithe é, is féidir emojis a chur isteach i dtéacs go héasca trí `:` a chlóscríobh, agus ainm emoji ina dhiaidh sin.", + "note_completion_enabled": "Cumasaigh uath-chríochnú nótaí", + "note_completion_description": "Más cumasaithe é, is féidir naisc chuig nótaí a chruthú trí `@` a chlóscríobh agus teideal an nóta ina dhiaidh sin.", + "slash_commands_enabled": "Cumasaigh orduithe slaise", + "slash_commands_description": "Más cumasaithe é, is féidir orduithe eagarthóireachta amhail briseadh líne nó ceannteidil a chur isteach a athrú trí `/` a chlóscríobh." + }, + "table_view": { + "new-row": "Sraith nua", + "new-column": "Colún nua", + "sort-column-by": "Sórtáil de réir \"{{title}}\"", + "sort-column-ascending": "Ag dul suas", + "sort-column-descending": "Ag dul síos", + "sort-column-clear": "Glan sórtáil", + "hide-column": "Folaigh colún \"{{title}}\"", + "show-hide-columns": "Taispeáin/folaigh colúin", + "row-insert-above": "Cuir isteach an tsraith thuas", + "row-insert-below": "Cuir isteach sraith thíos", + "row-insert-child": "Cuir nóta linbh isteach", + "add-column-to-the-left": "Cuir colún leis ar chlé", + "add-column-to-the-right": "Cuir colún leis ar dheis", + "edit-column": "Cuir colún in eagar", + "delete_column_confirmation": "An bhfuil tú cinnte gur mian leat an colún seo a scriosadh? Bainfear an tréith chomhfhreagrach as na nótaí go léir.", + "delete-column": "Scrios colún", + "new-column-label": "Lipéad", + "new-column-relation": "Gaol" + }, + "book_properties_config": { + "hide-weekends": "Folaigh deireadh seachtaine", + "display-week-numbers": "Taispeáin uimhreacha na seachtaine", + "map-style": "Stíl léarscáile", + "max-nesting-depth": "Doimhneacht neadaithe uasta:", + "raster": "Raster", + "vector_light": "Veicteoir (Solas)", + "vector_dark": "Veicteoir (Dorcha)", + "show-scale": "Taispeáin scála", + "show-labels": "Taispeáin ainmneacha marcóirí" + }, + "table_context_menu": { + "delete_row": "Scrios an tsraith" + }, + "board_view": { + "delete-note": "Scrios nóta...", + "remove-from-board": "Bain den bhord", + "archive-note": "Nóta cartlainne", + "unarchive-note": "Nóta díchartlannaithe", + "move-to": "Bog go", + "insert-above": "Cuir isteach thuas", + "insert-below": "Cuir isteach thíos", + "delete-column": "Scrios colún", + "delete-column-confirmation": "An bhfuil tú cinnte gur mian leat an colún seo a scriosadh? Scriosfar an tréith chomhfhreagrach sna nótaí faoin gcolún seo chomh maith.", + "new-item": "Mír nua", + "new-item-placeholder": "Cuir isteach teideal an nóta...", + "add-column": "Cuir Colún leis", + "add-column-placeholder": "Cuir isteach ainm an cholúin...", + "edit-note-title": "Cliceáil chun teideal an nóta a chur in eagar", + "edit-column-title": "Cliceáil chun teideal an cholúin a chur in eagar", + "column-already-exists": "Tá an colún seo ann cheana féin ar an mbord." + }, + "presentation_view": { + "edit-slide": "Cuir an sleamhnán seo in eagar", + "start-presentation": "Tosaigh an cur i láthair", + "slide-overview": "Forbhreathnú ar na sleamhnáin a athrú" + }, + "calendar_view": { + "delete_note": "Scrios nóta..." + }, + "command_palette": { + "tree-action-name": "Crann: {{name}}", + "export_note_title": "Nóta Easpórtála", + "export_note_description": "Easpórtáil an nóta reatha", + "show_attachments_title": "Taispeáin Ceangaltáin", + "show_attachments_description": "Féach ar cheangaltáin nótaí", + "search_notes_title": "Cuardaigh Nótaí", + "search_notes_description": "Oscail cuardach ardleibhéil", + "search_subtree_title": "Cuardaigh i bhFo-chrann", + "search_subtree_description": "Cuardaigh laistigh den fho-chrann reatha", + "search_history_title": "Taispeáin Stair Chuardaigh", + "search_history_description": "Féach ar chuardaigh roimhe seo", + "configure_launch_bar_title": "Cumraigh an Barra Seolta", + "configure_launch_bar_description": "Oscail cumraíocht an bharra lainseála, chun míreanna a chur leis nó a bhaint." + }, + "content_renderer": { + "open_externally": "Oscail go seachtrach" + }, + "modal": { + "close": "Dún", + "help_title": "Taispeáin tuilleadh eolais faoin scáileán seo" + }, + "call_to_action": { + "next_theme_title": "Bain triail as an téama nua Trilium", + "next_theme_message": "Tá an seantéama in úsáid agat faoi láthair, ar mhaith leat an téama nua a thriail?", + "next_theme_button": "Bain triail as an téama nua", + "background_effects_title": "Tá éifeachtaí cúlra cobhsaí anois", + "background_effects_message": "Ar fheistí Windows agus macOS, tá éifeachtaí cúlra cobhsaí anois. Cuireann na héifeachtaí cúlra teagmháil datha leis an gcomhéadan úsáideora tríd an gcúlra taobh thiar de a dhéanamh doiléir.", + "background_effects_button": "Cumasaigh éifeachtaí cúlra", + "new_layout_title": "Leagan amach nua", + "new_layout_message": "Thugamar leagan amach nuachóirithe isteach do Trilium. Baineadh an ribín agus comhtháthaíodh go gan uaim é sa phríomh-chomhéadan, le barra stádais nua agus rannóga inleathnaithe (amhail tréithe cur chun cinn) ag glacadh seilbhe ar phríomhfheidhmeanna.\n\nTá an leagan amach nua cumasaithe de réir réamhshocraithe, agus is féidir é a dhíchumasú go sealadach trí Roghanna → Dealramh.", + "new_layout_button": "Tuilleadh eolais", + "dismiss": "Díbhe" + }, + "settings": { + "related_settings": "Socruithe gaolmhara" + }, + "settings_appearance": { + "related_code_blocks": "Scéim dathanna do bhloic chóid i nótaí téacs", + "related_code_notes": "Scéim dathanna le haghaidh nótaí cóid", + "ui": "Comhéadan úsáideora", + "ui_old_layout": "Leagan amach sean", + "ui_new_layout": "Leagan amach nua" + }, + "units": { + "percentage": "%" + }, + "pagination": { + "total_notes": "{{count}} nótaí", + "prev_page": "Leathanach roimhe seo", + "next_page": "An chéad leathanach eile" + }, + "collections": { + "rendering_error": "Ní féidir ábhar a thaispeáint mar gheall ar earráid." + }, + "note-color": { + "clear-color": "Dath nóta soiléir", + "set-color": "Socraigh dath nóta", + "set-custom-color": "Socraigh dath nóta saincheaptha" + }, + "popup-editor": { + "maximize": "Athraigh go dtí an t-eagarthóir iomlán" + }, + "server": { + "unknown_http_error_title": "Earráid chumarsáide leis an bhfreastalaí", + "unknown_http_error_content": "Cód stádais: {{statusCode}}\nURL: {{method}} {{url}}\nTeachtaireacht: {{message}}", + "traefik_blocks_requests": "Má tá tú ag úsáid seachfhreastalaí droim ar ais Traefik, tugadh isteach athrú briste a théann i bhfeidhm ar an gcumarsáid leis an bhfreastalaí." + }, + "tab_history_navigation_buttons": { + "go-back": "Téigh ar ais go dtí an nóta roimhe seo", + "go-forward": "Téigh ar aghaidh go dtí an chéad nóta eile" + }, + "breadcrumb": { + "hoisted_badge": "Ardaithe", + "hoisted_badge_title": "Dí-ardaigh", + "workspace_badge": "Spás Oibre", + "scroll_to_top_title": "Léim go dtí tús an nóta", + "create_new_note": "Cruthaigh nóta nua do pháistí", + "empty_hide_archived_notes": "Folaigh nótaí cartlannaithe" + }, + "breadcrumb_badges": { + "read_only_explicit": "Léamh amháin", + "read_only_explicit_description": "Socraíodh an nóta seo de láimh go léamh amháin.\nCliceáil chun é a chur in eagar go sealadach.", + "read_only_auto": "Uathoibríoch inléite amháin", + "read_only_auto_description": "Socraíodh an nóta seo go huathoibríoch go mód léite amháin ar chúiseanna feidhmíochta. Is féidir an teorainn uathoibríoch seo a choigeartú ó na socruithe.\n\nCliceáil chun é a chur in eagar go sealadach.", + "read_only_temporarily_disabled": "In-eagarthóireacht shealadach", + "read_only_temporarily_disabled_description": "Is féidir an nóta seo a chur in eagar faoi láthair, ach is gnách go mbíonn sé inléite amháin. A luaithe a théann tú chuig nóta eile, beidh an nóta inléite amháin arís.\n\nCliceáil chun an modh inléite amháin a athchumasú.", + "shared_publicly": "Roinnte go poiblí", + "shared_locally": "Roinnte go háitiúil", + "shared_copy_to_clipboard": "Cóipeáil nasc chuig an ghearrthaisce", + "shared_open_in_browser": "Oscail nasc sa bhrabhsálaí", + "shared_unshare": "Bain an scair", + "clipped_note": "Gearrthóg gréasáin", + "clipped_note_description": "Tógadh an nóta seo ó {{url}} ar dtús.\n\nCliceáil chun nascleanúint a dhéanamh chuig an leathanach gréasáin foinseach.", + "execute_script": "Rith an script", + "execute_script_description": "Is nóta scripte é seo. Cliceáil chun an script a fhorghníomhú.", + "execute_sql": "Rith SQL", + "execute_sql_description": "Is nóta SQL é seo. Cliceáil chun an fiosrúchán SQL a fhorghníomhú.", + "save_status_saved": "Sábháilte", + "save_status_saving": "Ag sábháil...", + "save_status_unsaved": "Gan sábháil", + "save_status_error": "Theip ar shábháil", + "save_status_saving_tooltip": "Tá athruithe á sábháil.", + "save_status_unsaved_tooltip": "Tá athruithe neamhshábháilte ann. Sábhálfar iad go huathoibríoch i gceann nóiméid.", + "save_status_error_tooltip": "Tharla earráid agus an nóta á shábháil. Más féidir, déan iarracht ábhar an nóta a chóipeáil in áit eile agus an feidhmchlár a athlódáil." + }, + "status_bar": { + "language_title": "Athraigh teanga an ábhair", + "note_info_title": "Féach ar fhaisnéis nótaí (m.sh., dátaí, méid nótaí)", + "backlinks_one": "{{count}} nasc siar", + "backlinks_two": "{{count}} naisc siar", + "backlinks_few": "{{count}} naisc siar", + "backlinks_many": "{{count}} naisc siar", + "backlinks_other": "{{count}} naisc siar", + "backlinks_title_one": "Féach ar an nasc siar", + "backlinks_title_two": "Féach ar an naisc siar", + "backlinks_title_few": "Féach ar an naisc siar", + "backlinks_title_many": "Féach ar an naisc siar", + "backlinks_title_other": "Féach ar an naisc siar", + "attachments_one": "{{count}} ceangaltán", + "attachments_two": "{{count}} ceangaltáin", + "attachments_few": "{{count}} ceangaltáin", + "attachments_many": "{{count}} ceangaltáin", + "attachments_other": "{{count}} ceangaltáin", + "attachments_title_one": "Féach ar an gceangaltán i gcluaisín nua", + "attachments_title_two": "Féach ar cheangaltán i gcluaisíní nua", + "attachments_title_few": "Féach ar cheangaltán i gcluaisíní nua", + "attachments_title_many": "Féach ar cheangaltán i gcluaisíní nua", + "attachments_title_other": "Féach ar cheangaltán i gcluaisíní nua", + "attributes_one": "{{count}} tréith", + "attributes_two": "{{count}} tréithe", + "attributes_few": "{{count}} tréithe", + "attributes_many": "{{count}} tréithe", + "attributes_other": "{{count}} tréithe", + "attributes_title": "Tréithe faoi úinéireacht agus tréithe oidhreachta", + "note_paths_one": "{{count}} cosán", + "note_paths_two": "{{count}} cosáin", + "note_paths_few": "{{count}} cosáin", + "note_paths_many": "{{count}} cosáin", + "note_paths_other": "{{count}} cosáin", + "note_paths_title": "Cosáin nótaí", + "code_note_switcher": "Athraigh mód teanga" + }, + "attributes_panel": { + "title": "Tréithe Nóta" + }, + "right_pane": { + "empty_message": "Níl aon rud le taispeáint don nóta seo", + "empty_button": "Folaigh an painéal", + "toggle": "Athraigh an painéal ar dheis", + "custom_widget_go_to_source": "Téigh go dtí an cód foinse" + }, + "pdf": { + "attachments_one": "{{count}} ceangaltán", + "attachments_two": "{{count}} ceangaltáin", + "attachments_few": "{{count}} ceangaltáin", + "attachments_many": "{{count}} ceangaltáin", + "attachments_other": "{{count}} ceangaltáin", + "layers_one": "{{count}} sraith", + "layers_two": "{{count}} sraitheanna", + "layers_few": "{{count}} sraitheanna", + "layers_many": "{{count}} sraitheanna", + "layers_other": "{{count}} sraitheanna", + "pages_one": "{{count}} leathanach", + "pages_two": "{{count}} leathanaigh", + "pages_few": "{{count}} leathanaigh", + "pages_many": "{{count}} leathanaigh", + "pages_other": "{{count}} leathanaigh", + "pages_alt": "Leathanach {{pageNumber}}", + "pages_loading": "Ag lódáil..." + }, + "platform_indicator": { + "available_on": "Ar fáil ar {{platform}}" + }, + "mobile_tab_switcher": { + "title_one": "{{count}} cluaisín", + "title_two": "{{count}} cluaisíní", + "title_few": "{{count}} cluaisíní", + "title_many": "{{count}} cluaisíní", + "title_other": "{{count}} cluaisíní", + "more_options": "Tuilleadh roghanna" + }, + "bookmark_buttons": { + "bookmarks": "Leabharmharcanna" + }, + "web_view_setup": { + "title": "Cruthaigh radharc beo de leathanach gréasáin go díreach isteach i Trilium", + "url_placeholder": "Cuir isteach nó greamaigh seoladh an tsuímh ghréasáin, mar shampla https://triliumnotes.org", + "create_button": "Cruthaigh Radharc Gréasáin", + "invalid_url_title": "Seoladh neamhbhailí", + "invalid_url_message": "Cuir isteach seoladh gréasáin bailí, mar shampla https://triliumnotes.org.", + "disabled_description": "Iompórtáladh an radharc gréasáin seo ó fhoinse sheachtrach. Chun cabhrú leat a chosaint ar ábhar fioscaireachta nó mailíseach, níl sé ag lódáil go huathoibríoch. Is féidir leat é a chumasú má tá muinín agat as an bhfoinse.", + "disabled_button_enable": "Cumasaigh radharc gréasáin" + }, + "render": { + "setup_title": "Taispeáin HTML saincheaptha nó Preact JSX taobh istigh den nóta seo", + "setup_create_sample_preact": "Cruthaigh nóta samplach le Preact", + "setup_create_sample_html": "Cruthaigh nóta samplach le HTML", + "setup_sample_created": "Cruthaíodh nóta samplach mar nóta linbh.", + "disabled_description": "Tagann na nótaí rindreála seo ó fhoinse sheachtrach. Chun tú a chosaint ar ábhar mailíseach, níl sé cumasaithe de réir réamhshocraithe. Déan cinnte go bhfuil muinín agat as an bhfoinse sula gcumasaíonn tú é.", + "disabled_button_enable": "Cumasaigh nóta rindreála" + }, + "active_content_badges": { + "type_icon_pack": "Pacáiste deilbhín", + "type_backend_script": "Script chúltaca", + "type_frontend_script": "Script tosaigh", + "type_widget": "Giuirléid", + "type_app_css": "CSS saincheaptha", + "type_render_note": "Nóta rindreála", + "type_web_view": "Radharc gréasáin", + "type_app_theme": "Téama saincheaptha", + "toggle_tooltip_enable_tooltip": "Cliceáil chun an {{type}} seo a chumasú.", + "toggle_tooltip_disable_tooltip": "Cliceáil chun an {{type}} seo a dhíchumasú.", + "menu_docs": "Doiciméadú oscailte", + "menu_execute_now": "Rith an script anois", + "menu_run": "Rith go huathoibríoch", + "menu_run_disabled": "De láimh", + "menu_run_backend_startup": "Nuair a thosaíonn an cúltaca", + "menu_run_hourly": "Gach uair an chloig", + "menu_run_daily": "Laethúil", + "menu_run_frontend_startup": "Nuair a thosaíonn tosaigh an deisce", + "menu_run_mobile_startup": "Nuair a thosaíonn an taobhlíne soghluaiste", + "menu_change_to_widget": "Athraigh go giuirléid", + "menu_change_to_frontend_script": "Athraigh chuig an script tosaigh", + "menu_theme_base": "Bunús téama" + }, + "setup_form": { + "more_info": "Foghlaim níos mó" + } +} diff --git a/apps/client/src/translations/id/translation.json b/apps/client/src/translations/id/translation.json index 930eecf5e5..157f406053 100644 --- a/apps/client/src/translations/id/translation.json +++ b/apps/client/src/translations/id/translation.json @@ -50,7 +50,8 @@ "save": "Simpan", "branch_prefix_saved": "Prefiks cabang telah disimpan.", "branch_prefix_saved_multiple": "Prefix cabang telah disimpan pada {{count}} cabang.", - "affected_branches": "Cabang terdampak ({{count}}):" + "affected_branches": "Cabang terdampak ({{count}}):", + "edit_branch_prefix": "Sunting awalan cabang" }, "bulk_actions": { "bulk_actions": "Aksi borongan", @@ -61,14 +62,18 @@ "execute_bulk_actions": "Eksekusi aksi borongan", "bulk_actions_executed": "Aksi borongan telah di eksekusi dengan sukses.", "none_yet": "Belum ada... tambahkan aksi dengan memilih salah satu dari aksi di atas.", - "labels": "Label-label" + "labels": "Label-label", + "relations": "Hubungan", + "notes": "Catatan", + "other": "Lainnya" }, "confirm": { "cancel": "Batal", "ok": "Oke", "are_you_sure_remove_note": "Apakah anda yakin mau membuang catatan \"{{title}}\" dari peta relasi? ", "if_you_dont_check": "Jika Anda tidak mencentang ini, catatan hanya akan dihapus dari peta relasi.", - "also_delete_note": "Hapus juga catatannya" + "also_delete_note": "Hapus juga catatannya", + "confirmation": "Konfirmasi" }, "delete_notes": { "delete_notes_preview": "Hapus pratinjau catatan", @@ -77,9 +82,19 @@ "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.", "erase_notes_warning": "Hapus catatan secara permanen (tidak bisa dikembalikan), termasuk semua duplikat. Aksi akan memaksa aplikasi untuk mengulang kembali.", "notes_to_be_deleted": "Catatan-catatan berikut akan dihapuskan ({{notesCount}})", - "no_note_to_delete": "Tidak ada Catatan yang akan dihapus (hanya duplikat)." + "no_note_to_delete": "Tidak ada Catatan yang akan dihapus (hanya duplikat).", + "broken_relations_to_be_deleted": "Hubungan berikut akan diputus dan dihapus ({{ relationCount}})" }, "clone_to": { - "clone_notes_to": "Duplikat catatan ke…" + "clone_notes_to": "Duplikat catatan ke…", + "help_on_links": "Bantuan pada tautan", + "notes_to_clone": "Catatan untuk kloning", + "target_parent_note": "Sasaran catatan utama", + "search_for_note_by_its_name": "cari catatan berdasarkan namanya", + "cloned_note_prefix_title": "Catatan yang dikloning akan ditampilkan diruntutan catatan dengan awalan yang diberikan", + "prefix_optional": "Awalan (opsional)", + "clone_to_selected_note": "Salin ke catatan yang dipilih", + "no_path_to_clone_to": "Tidak ada jalur untuk digandakan.", + "note_cloned": "Catatan \"{{clonedTitle}}\" telah digandakan ke dalam \"{{targetTitle}}\"" } } diff --git a/apps/client/src/translations/it/translation.json b/apps/client/src/translations/it/translation.json index 89e44794c1..f24d449fcb 100644 --- a/apps/client/src/translations/it/translation.json +++ b/apps/client/src/translations/it/translation.json @@ -167,8 +167,8 @@ "desktop-application": "Applicazione Desktop", "native-title-bar": "Barra del titolo nativa", "native-title-bar-description": "Su Windows e macOS, disattivare la barra del titolo nativa rende l'applicazione più compatta. Su Linux, attivarla si integra meglio con il resto del sistema.", - "background-effects": "Abilita effetti di sfondo (solo Windows 11)", - "background-effects-description": "L'effetto Mica aggiunge uno sfondo sfocato ed elegante alle finestre delle app, creando profondità e un aspetto moderno. La \"Barra del titolo nativa\" deve essere disattivata.", + "background-effects": "Abilita effetti di sfondo", + "background-effects-description": "Aggiunge uno sfondo sfocato ed elegante alle finestre dell'app, creando profondità e un look moderno. La \"barra del titolo nativa\" deve essere disabilitata.", "restart-app-button": "Riavviare l'applicazione per visualizzare le modifiche" }, "note_autocomplete": { @@ -186,7 +186,8 @@ "geo-map": { "create-child-note-title": "Crea una nota figlia e aggiungila alla mappa", "create-child-note-instruction": "Clicca sulla mappa per creare una nuova nota qui o premi Escape per uscire.", - "unable-to-load-map": "Impossibile caricare la mappa." + "unable-to-load-map": "Impossibile caricare la mappa.", + "create-child-note-text": "Aggiungi indicatore" }, "geo-map-context": { "open-location": "Apri la posizione", @@ -368,7 +369,8 @@ "description": "Descrizione", "reload_app": "Ricarica l'app per applicare le modifiche", "set_all_to_default": "Imposta tutte le scorciatoie sui valori predefiniti", - "confirm_reset": "Vuoi davvero ripristinare tutte le scorciatoie da tastiera ai valori predefiniti?" + "confirm_reset": "Vuoi davvero ripristinare tutte le scorciatoie da tastiera ai valori predefiniti?", + "no_results": "Nessuna scorciatoia trovata corrispondente '{{filter}}'" }, "shared_switch": { "toggle-on-title": "Condividi la nota", @@ -422,7 +424,8 @@ "unknown_search_option": "Opzione di ricerca sconosciuta {{searchOptionName}}", "search_note_saved": "La nota di ricerca è stata salvata in {{- notePathTitle}}", "actions_executed": "Le azioni sono state eseguite.", - "view_options": "Opzioni di visualizzazione:" + "view_options": "Opzioni di visualizzazione:", + "option": "opzione" }, "modal": { "close": "Chiudi", @@ -1241,7 +1244,8 @@ "show-cheatsheet": "Mostra il foglietto illustrativo", "toggle-zen-mode": "Modalità Zen", "new-version-available": "Nuovo aggiornamento disponibile", - "download-update": "Ottieni la versione {{latestVersion}}" + "download-update": "Ottieni la versione {{latestVersion}}", + "search_notes": "Cerca note" }, "zen_mode": { "button_exit": "Esci dalla modalità Zen" @@ -1324,7 +1328,7 @@ "button_title": "Esporta diagramma come SVG" }, "relation_map_buttons": { - "create_child_note_title": "Crea una nuova nota secondaria e aggiungila a questa mappa delle relazioni", + "create_child_note_title": "Crea una nota secondaria e aggiungila alla mappa", "reset_pan_zoom_title": "Ripristina panoramica e zoom alle coordinate e all'ingrandimento iniziali", "zoom_in_title": "Ingrandisci", "zoom_out_title": "Rimpicciolisci" @@ -1340,7 +1344,9 @@ "delete_this_note": "Elimina questa nota", "note_revisions": "Revisioni delle note", "error_cannot_get_branch_id": "Impossibile ottenere branchId per notePath '{{notePath}}'", - "error_unrecognized_command": "Comando non riconosciuto {{command}}" + "error_unrecognized_command": "Comando non riconosciuto {{command}}", + "backlinks": "Backlinks", + "content_language_switcher": "Lingua dei contenuti: {{language}}" }, "note_icon": { "change_note_icon": "Cambia icona nota", @@ -1521,7 +1527,7 @@ "no_attachments": "Questa nota non ha allegati." }, "book": { - "no_children_help": "Questa raccolta non ha note secondarie, quindi non c'è nulla da visualizzare. Consulta la wiki per i dettagli.", + "no_children_help": "Questa raccolta non ha note secondarie, quindi non c'è nulla da visualizzare.", "drag_locked_title": "Bloccato per la modifica", "drag_locked_message": "Trascinamento non consentito poiché la raccolta è bloccata per la modifica." }, @@ -1577,15 +1583,6 @@ "default_new_note_title": "nuova nota", "click_on_canvas_to_place_new_note": "Clicca sulla tela per inserire una nuova nota" }, - "render": { - "note_detail_render_help_1": "Questa nota di aiuto viene visualizzata perché questa nota di tipo Render HTML non ha la relazione richiesta per funzionare correttamente.", - "note_detail_render_help_2": "Il tipo di nota HTML Render viene utilizzato per lo scripting. In breve, si ottiene una nota in codice HTML (opzionalmente con un po' di JavaScript) che verrà visualizzata. Per farla funzionare, è necessario definire una relazione denominata \"renderNote\" che punti alla nota HTML da visualizzare." - }, - "web_view": { - "web_view": "Visualizzazione Web", - "embed_websites": "La nota di tipo Web View consente di incorporare siti web in Trilium.", - "create_label": "Per iniziare, crea un'etichetta con l'indirizzo URL che desideri incorporare, ad esempio #webViewSrc=\"https://www.google.com\"" - }, "vacuum_database": { "title": "Pulizia del database", "description": "Questa operazione ricostruirà il database, generando in genere un file di dimensioni inferiori. In realtà, nessun dato verrà modificato.", @@ -1923,7 +1920,9 @@ "print_report_collection_content_many": "{{count}} le note nella raccolta non possono essere stampate perché non sono supportate o sono protette.", "print_report_collection_content_other": "{{count}} le note nella raccolta non possono essere stampate perché non sono supportate o sono protette.", "print_report_collection_details_button": "Vedi dettagli", - "print_report_collection_details_ignored_notes": "Note ignorate" + "print_report_collection_details_ignored_notes": "Note ignorate", + "print_report_error_title": "Impossibile stampare", + "print_report_stack_trace": "Traccia dello stack" }, "note_title": { "placeholder": "scrivi qui il titolo della nota...", @@ -2110,7 +2109,8 @@ "raster": "Trama", "vector_light": "Vettore (Luce)", "vector_dark": "Vettore (scuro)", - "show-scale": "Mostra scala" + "show-scale": "Mostra scala", + "show-labels": "Mostra nomi dei marcatori" }, "table_context_menu": { "delete_row": "Elimina riga" @@ -2143,9 +2143,9 @@ "next_theme_message": "Al momento stai utilizzando il tema legacy. Vuoi provare il nuovo tema?", "next_theme_button": "Prova il nuovo tema", "background_effects_title": "Gli effetti di sfondo sono ora stabili", - "background_effects_message": "Sui dispositivi Windows, gli effetti di sfondo sono ora completamente stabili. Gli effetti di sfondo aggiungono un tocco di colore all'interfaccia utente sfocando lo sfondo retrostante. Questa tecnica è utilizzata anche in altre applicazioni come Esplora risorse di Windows.", + "background_effects_message": "Su dispositivi Windows e macOS, gli effetti di sfondo sono ora stabili. Gli effetti di sfondo aggiungono un tocco di colore all'interfaccia utente sfocando lo sfondo dietro di essa.", "background_effects_button": "Abilita gli effetti di sfondo", - "dismiss": "Congedare", + "dismiss": "Chiudi", "new_layout_title": "Nuovo layout", "new_layout_message": "Abbiamo introdotto un layout modernizzato per Trilium. La barra multifunzione è stata rimossa e integrata perfettamente nell'interfaccia principale, con una nuova barra di stato e sezioni espandibili (come gli attributi promossi) che assumono le funzioni chiave.\n\nIl nuovo layout è abilitato di default e può essere temporaneamente disabilitato tramite Opzioni → Aspetto.", "new_layout_button": "Maggiori informazioni" @@ -2164,7 +2164,6 @@ "percentage": "%" }, "pagination": { - "page_title": "Pagina di {{startIndex}} - {{endIndex}}", "total_notes": "{{count}} note" }, "collections": { @@ -2281,5 +2280,61 @@ "pages_other": "{{count}} pagine", "pages_alt": "Pagina {{pageNumber}}", "pages_loading": "Caricamento in corso..." + }, + "web_view_setup": { + "title": "Crea una visualizzazione live di una pagina web direttamente in Trilium", + "url_placeholder": "Inserisci o incolla l'indirizzo del sito web, ad esempio https://triliumnotes.org", + "create_button": "Crea vista Web", + "invalid_url_title": "Indirizzo non valido", + "invalid_url_message": "Inserisci un indirizzo web valido, ad esempio https://triliumnotes.org.", + "disabled_description": "Questa visualizzazione web è stata importata da una fonte esterna. Per proteggerti dal phishing o da contenuti dannosi, non viene caricata automaticamente. Puoi abilitarla se ritieni che la fonte sia affidabile.", + "disabled_button_enable": "Abilita visualizzazione web" + }, + "platform_indicator": { + "available_on": "Disponibile su {{platform}}" + }, + "mobile_tab_switcher": { + "title_one": "Scheda {{count}}", + "title_many": "Schede {{count}}", + "title_other": "Schede {{count}}", + "more_options": "Altre opzioni" + }, + "bookmark_buttons": { + "bookmarks": "Segnalibri" + }, + "render": { + "setup_title": "Visualizza HTML personalizzato o Preact JSX all'interno di questa nota", + "setup_create_sample_preact": "Crea una nota di esempio con Preact", + "setup_create_sample_html": "Crea una nota di esempio con HTML", + "setup_sample_created": "È stata creata una nota di esempio come nota secondaria.", + "disabled_description": "Queste note di rendering provengono da una fonte esterna. Per proteggerti da contenuti dannosi, non sono abilitate per impostazione predefinita. Assicurati di fidarti della fonte prima di abilitarle.", + "disabled_button_enable": "Abilita nota di rendering" + }, + "active_content_badges": { + "type_icon_pack": "Pacchetto icone", + "type_backend_script": "Script di backend", + "type_frontend_script": "Script frontend", + "type_widget": "Widget", + "type_app_css": "CSS personalizzato", + "type_render_note": "Nota di rendering", + "type_web_view": "Visualizzazione web", + "type_app_theme": "Tema personalizzato", + "toggle_tooltip_enable_tooltip": "Clicca per abilitare questa funzione {{type}}.", + "toggle_tooltip_disable_tooltip": "Clicca per disattivare questa funzione {{type}}.", + "menu_docs": "Documentazione aperta", + "menu_execute_now": "Esegui lo script ora", + "menu_run": "Esegui automaticamente", + "menu_run_disabled": "Manualmente", + "menu_run_backend_startup": "Quando il backend si avvia", + "menu_run_hourly": "Ogni ora", + "menu_run_daily": "Giornaliero", + "menu_run_frontend_startup": "Quando si avvia il frontend desktop", + "menu_run_mobile_startup": "Quando si avvia il frontend mobile", + "menu_change_to_widget": "Passa al widget", + "menu_change_to_frontend_script": "Modifica allo script frontend", + "menu_theme_base": "Tema base" + }, + "setup_form": { + "more_info": "Per saperne di più" } } diff --git a/apps/client/src/translations/ja/translation.json b/apps/client/src/translations/ja/translation.json index 4d6f72caab..618166ad00 100644 --- a/apps/client/src/translations/ja/translation.json +++ b/apps/client/src/translations/ja/translation.json @@ -81,7 +81,8 @@ "configure_launchbar": "ランチャーバーの設定", "show_shared_notes_subtree": "共有ノートのサブツリーを表示", "new-version-available": "新しいアップデートが利用可能", - "download-update": "{{latestVersion}} をバージョンを入手" + "download-update": "{{latestVersion}} をバージョンを入手", + "search_notes": "検索ノート" }, "left_pane_toggle": { "show_panel": "パネルを表示", @@ -234,7 +235,8 @@ "search_note_saved": "検索ノートが {{- notePathTitle}} に保存されました", "actions_executed": "アクションが実行されました。", "ancestor": "祖先:", - "view_options": "表示オプション:" + "view_options": "表示オプション:", + "option": "オプション" }, "shortcuts": { "multiple_shortcuts": "同じアクションに対して複数のショートカットを設定する場合、カンマで区切ることができます。", @@ -247,7 +249,8 @@ "reload_app": "リロードして変更を適用する", "set_all_to_default": "すべてのショートカットをデフォルトに戻す", "confirm_reset": "キーボードショートカットをすべてデフォルトにリセットしますか?", - "keyboard_shortcuts": "キーボードショートカット" + "keyboard_shortcuts": "キーボードショートカット", + "no_results": "'{{filter}}' に一致するショートカットが見つかりません" }, "confirm": { "confirmation": "確認", @@ -407,7 +410,7 @@ "relation_map_buttons": { "zoom_out_title": "ズームアウト", "zoom_in_title": "ズームイン", - "create_child_note_title": "新しい子ノートを作成し、関連マップに追加", + "create_child_note_title": "子ノートを作成し、マップに追加", "reset_pan_zoom_title": "パンとズームを初期座標と倍率にリセット" }, "tree-context-menu": { @@ -824,11 +827,6 @@ "error_no_path": "移動するパスがありません。", "move_success_message": "選択したノートは以下に移動されました " }, - "web_view": { - "web_view": "Web ビュー", - "embed_websites": "Web ビュータイプでは、web サイトを Trilium に埋め込むことができます。", - "create_label": "まず始めに、埋め込みたいURLアドレスのラベルを作成してください。例: #webViewSrc=\"https://www.google.com\"" - }, "backend_log": { "refresh": "リフレッシュ" }, @@ -1648,7 +1646,9 @@ "error_unrecognized_command": "認識されないコマンド {{command}}", "insert_child_note": "子ノートを挿入", "error_cannot_get_branch_id": "ノートパス 「{{notePath}} のbranchIdを取得できません", - "note_revisions": "ノートの変更履歴" + "note_revisions": "ノートの変更履歴", + "backlinks": "バックリンク", + "content_language_switcher": "コンテンツの言語: {{language}}" }, "inherited_attribute_list": { "title": "継承属性", @@ -1860,10 +1860,6 @@ "protecting-title": "保護の状態", "unprotecting-title": "保護解除の状態" }, - "render": { - "note_detail_render_help_1": "このヘルプノートが表示されるのは、このノートの「HTML のレンダリング」タイプには、正常に機能するために必要なリレーションがないためです。", - "note_detail_render_help_2": "レンダリングHTMLノートタイプは、スクリプティングに使用されます。簡単に言うと、HTMLコードノート(オプションでJavaScriptを含む)があり、このノートがそれをレンダリングします。これを動作させるには、レンダリングするHTMLノートを指す「renderNote」というリレーションを定義する必要があります。" - }, "consistency_checks": { "find_and_fix_button": "一貫性の問題を見つけて修正する", "finding_and_fixing_message": "一貫性の問題を見つけて修正中…", @@ -1955,7 +1951,9 @@ "print_report_title": "レポートを印刷", "print_report_collection_content_other": "コレクション内の {{count}} 件のノートは、サポートされていないか保護されているため、印刷できませんでした。", "print_report_collection_details_button": "詳細を見る", - "print_report_collection_details_ignored_notes": "無視されたノート" + "print_report_collection_details_ignored_notes": "無視されたノート", + "print_report_error_title": "印刷に失敗しました", + "print_report_stack_trace": "スタックトレース" }, "watched_file_update_status": { "ignore_this_change": "この変更を無視する", @@ -2008,7 +2006,8 @@ "geo-map": { "create-child-note-title": "新しい子ノートを作成し、マップに追加する", "create-child-note-instruction": "地図をクリックしてその場所に新しいノートを作成するか、Esc キーを押して閉じます。", - "unable-to-load-map": "マップを読み込めません。" + "unable-to-load-map": "マップを読み込めません。", + "create-child-note-text": "マーカーを追加" }, "geo-map-context": { "open-location": "現在位置を表示", @@ -2037,7 +2036,8 @@ "show-scale": "スケールを表示", "raster": "Raster", "vector_light": "Vector(ライト)", - "vector_dark": "Vector (ダーク)" + "vector_dark": "Vector (ダーク)", + "show-labels": "マーカー名を表示" }, "call_to_action": { "next_theme_title": "新しいTriliumテーマをお試しください", @@ -2065,8 +2065,9 @@ "percentage": "%" }, "pagination": { - "page_title": "{{startIndex}} - {{endIndex}} ページ", - "total_notes": "{{count}} ノート" + "total_notes": "{{count}} ノート", + "prev_page": "前のページ", + "next_page": "次のページ" }, "collections": { "rendering_error": "エラーのためコンテンツを表示できません。" @@ -2094,7 +2095,7 @@ "no_attachments": "このノートには添付ファイルはありません。" }, "book": { - "no_children_help": "このコレクションには子ノートがないため、表示するものがありません。詳細はwikiをご覧ください。", + "no_children_help": "このコレクションには子ノートがないため、表示するものがありません。", "drag_locked_title": "編集をロック中", "drag_locked_message": "コレクションは編集がロックされているため、ドラッグは許可されていません。" }, @@ -2256,5 +2257,56 @@ }, "platform_indicator": { "available_on": "{{platform}} で利用可能" + }, + "mobile_tab_switcher": { + "title_other": "{{count}} タブ", + "more_options": "その他のオプション" + }, + "bookmark_buttons": { + "bookmarks": "ブックマーク" + }, + "web_view_setup": { + "title": "Trilium に直接 Web ページのライブビューを作成", + "url_placeholder": "Web サイトのアドレスを入力または貼り付けて下さい。 例: https://triliumnotes.org", + "create_button": "Web ビューを作成", + "invalid_url_title": "無効なアドレス", + "invalid_url_message": "有効な Web アドレスを入力してください。 例: https://triliumnotes.org", + "disabled_description": "この Web ビューは外部ソースからインポートされました。フィッシングや悪意のあるコンテンツから保護するため、自動的には読み込まれません。ソースを信頼できる場合は、有効にすることができます。", + "disabled_button_enable": "Web ビューを有効" + }, + "render": { + "setup_title": "このノート内にカスタム HTML または Preact JSX を表示", + "setup_create_sample_preact": "Preact でサンプルノートを作成", + "setup_create_sample_html": "HTML でサンプルノートを作成", + "setup_sample_created": "子ノートとしてサンプルノートが作成されました。", + "disabled_description": "このレンダリングノートは外部ソースから提供されています。悪意のあるコンテンツからユーザーを保護するため、デフォルトでは有効になっていません。有効にする前に、ソースが信頼できるかどうかをご確認ください。", + "disabled_button_enable": "レンダリングノートを有効" + }, + "active_content_badges": { + "type_icon_pack": "アイコンパック", + "type_backend_script": "バックエンドスクリプト", + "type_frontend_script": "フロントエンドスクリプト", + "type_widget": "ウィジェット", + "type_app_css": "カスタム CSS", + "type_render_note": "レンダリングノート", + "type_web_view": "Web ビュー", + "type_app_theme": "カスタムテーマ", + "toggle_tooltip_enable_tooltip": "この {{type}} を有効にするにはクリックしてください。", + "toggle_tooltip_disable_tooltip": "この {{type}} を無効にするにはクリックしてください。", + "menu_docs": "ドキュメントを開く", + "menu_execute_now": "今すぐスクリプトを実行", + "menu_run": "自動で実行", + "menu_run_disabled": "手動で実行", + "menu_run_backend_startup": "バックエンドの起動時", + "menu_run_hourly": "毎時", + "menu_run_daily": "毎日", + "menu_run_frontend_startup": "デスクトップ フロントエンドの起動時", + "menu_run_mobile_startup": "モバイル フロントエンドの起動時", + "menu_change_to_widget": "ウィジェットの変更", + "menu_change_to_frontend_script": "フロントエンドスクリプトの変更", + "menu_theme_base": "テーマベース" + }, + "setup_form": { + "more_info": "さらに詳しく" } } diff --git a/apps/client/src/translations/ko/translation.json b/apps/client/src/translations/ko/translation.json index aefb75c6ef..bf4ac7b6bd 100644 --- a/apps/client/src/translations/ko/translation.json +++ b/apps/client/src/translations/ko/translation.json @@ -21,8 +21,17 @@ }, "bundle-error": { "title": "사용자 정의 스크립트를 불러오는데 실패했습니다", - "message": "ID가 \"{{id}}\"고, 제목이 \"{{title}}\"인 노트에서 스크립트가 실행되지 못했습니다:\n\n{{message}}" - } + "message": "다음 이유로 인해 스크립트가 실행되지 못했습니다:\n\n{{message}}" + }, + "widget-list-error": { + "title": "서버에서 위젯 목록을 가져오는 데 실패했습니다" + }, + "widget-render-error": { + "title": "사용자 정의 React 위젯을 렌더링하는 데 실패했습니다" + }, + "widget-missing-parent": "사용자 정의 위젯에 필수 속성 '{{property}}'가 정의되어 있지 않습니다.\n\n이 스크립트를 UI 요소 없이 실행하려면 '#run=frontendStartup'을 대신 사용하십시오.", + "open-script-note": "스크립트 노트 열기", + "scripting-error": "사용자 지정 스크립트 오류: {{title}}" }, "add_link": { "add_link": "링크 추가", @@ -41,7 +50,8 @@ "prefix": "접두사: ", "branch_prefix_saved": "브랜치 접두사가 저장되었습니다.", "edit_branch_prefix_multiple": "{{count}}개의 지점 접두사 편집", - "branch_prefix_saved_multiple": "{{count}}개의 지점에 대해 지점 접두사가 저장되었습니다." + "branch_prefix_saved_multiple": "{{count}}개의 지점에 대해 지점 접두사가 저장되었습니다.", + "affected_branches": "영향을 받는 브랜치 수 ({{count}}):" }, "bulk_actions": { "bulk_actions": "대량 작업", @@ -64,10 +74,66 @@ "first-week-contains-first-day": "첫 번째 주에는 올해의 첫날이 포함됩니다" }, "clone_to": { - "clone_notes_to": "~로 노트 복제", + "clone_notes_to": "노트 클론하기...", "help_on_links": "링크에 대한 도움말", "notes_to_clone": "노트 클론 생성", "target_parent_note": "부모 노트 타겟", - "search_for_note_by_its_name": "이름으로 노트 검색하기" + "search_for_note_by_its_name": "이름으로 노트 검색하기", + "no_path_to_clone_to": "클론할 경로가 존재하지 않습니다.", + "note_cloned": "노트 \"{{clonedTitle}}\"이(가) \"{{targetTitle}}\"로 클론되었습니다", + "cloned_note_prefix_title": "클론된 노트는 지정된 접두사와 함께 노트 트리에 표시됩니다", + "prefix_optional": "접두사 (선택 사항)", + "clone_to_selected_note": "선택한 노트에 클론" + }, + "confirm": { + "confirmation": "확인", + "cancel": "취소", + "ok": "OK", + "are_you_sure_remove_note": "관계 맵에서 \"{{title}}\" 노트를 정말로 제거하시겠습니까? ", + "if_you_dont_check": "이 항목을 선택하지 않으면 해당 노트는 관계 맵에서만 제거됩니다.", + "also_delete_note": "노트를 함께 삭제" + }, + "delete_notes": { + "erase_notes_description": "일반(소프트) 삭제는 메모를 삭제된 것으로 표시하는 것일 뿐이며, 일정 시간 동안 (최근 변경 내용 대화 상자에서) 복구할 수 있습니다. 이 옵션을 선택하면 메모가 즉시 삭제되며 복구할 수 없습니다.", + "erase_notes_warning": "모든 복제본을 포함하여 메모를 영구적으로 삭제합니다(이 작업은 되돌릴 수 없습니다). 애플리케이션이 다시 시작됩니다.", + "notes_to_be_deleted": "다음 노트가 삭제됩니다 ({{notesCount}})", + "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": "모든 복제본 삭제(최근 변경 사항에서 되돌릴 수 있습니다)" + }, + "export": { + "export_note_title": "노트 내보내기", + "export_type_single": "이 노트에만 해당(후손 노트를 포함하지 않음)", + "export": "내보내기", + "choose_export_type": "내보내기 타입을 선택해 주세요", + "export_status": "상태 내보내기", + "export_in_progress": "내보내기 진행 중: {{progressCount}}", + "export_finished_successfully": "내보내기를 성공적으로 완료했습니다.", + "format_pdf": "PDF - 인쇄 또는 공유용", + "share-format": "웹 게시용 HTML - 공유 노트에 사용되는 것과 동일한 테마를 사용하지만 정적 웹사이트로 게시할 수 있습니다.", + "close": "닫기", + "export_type_subtree": "이 노트와 모든 후손 노트", + "format_html": "HTML - 모든 형식 유지됨, 권장", + "format_html_zip": "HTML(ZIP 아카이브) - 모든 서식이 유지됨, 권장.", + "format_markdown": "마크다운 - 대부분의 서식이 유지됩니다.", + "format_opml": "OPML은 텍스트 전용 아웃라이너 교환 형식입니다. 서식, 이미지 및 파일은 포함되지 않습니다.", + "opml_version_1": "OPML v1.0 - 일반 텍스트만", + "opml_version_2": "OPML v2.0 - HTML 지원" + }, + "help": { + "title": "치트 시트", + "editShortcuts": "키보드 단축키 편집", + "noteNavigation": "노트 내비게이션", + "goUpDown": "노트 목록에서 위/아래로 이동", + "collapseExpand": "노트 접기/펼치기", + "notSet": "미설정", + "goBackForwards": "히스토리에서 뒤로/앞으로 이동", + "showJumpToNoteDialog": "\"노트로 이동\" 대화 상자 표시", + "scrollToActiveNote": "활성화된 노트로 스크롤 이동" } } diff --git a/apps/client/src/translations/pl/translation.json b/apps/client/src/translations/pl/translation.json index 17f32fc602..2c690b0370 100644 --- a/apps/client/src/translations/pl/translation.json +++ b/apps/client/src/translations/pl/translation.json @@ -21,7 +21,7 @@ }, "bundle-error": { "title": "Nie udało się załadować niestandardowego skryptu", - "message": "Skrypt z notatki o ID \"{{id}}\", zatytułowany \"{{title}}\", nie mógł zostać wykonany z powodu:\n\n{{message}}" + "message": "Skrypt nie mógł zostać wykonany z powodu:\n\n{{message}}" }, "widget-list-error": { "title": "Nie udało się pobrać listy widżetów z serwera" @@ -29,8 +29,9 @@ "widget-render-error": { "title": "Nie udało się wyrenderować niestandardowego widżetu React" }, - "widget-missing-parent": "Niestandardowy widżet nie ma zdefiniowanej obowiązkowej właściwości „{{property}}”.", - "open-script-note": "Otwórz notatkę ze skryptem" + "widget-missing-parent": "Niestandardowy widżet nie ma zdefiniowanej obowiązkowej właściwości „{{property}}”.\nJeśli skrypt ma działać bez interfejsu użytkownika (UI) wyłącz go: '#run=frontendStartup'.", + "open-script-note": "Otwórz notatkę ze skryptem", + "scripting-error": "Błąd skryptu użytkownika: {{title}}" }, "add_link": { "add_link": "Dodaj link", @@ -191,7 +192,8 @@ "expand_tooltip": "Rozwija bezpośrednie elementy podrzędne tej kolekcji (o jeden poziom). Aby uzyskać więcej opcji, naciśnij strzałkę po prawej.", "expand_first_level": "Rozwiń bezpośrednie elementy podrzędne", "expand_nth_level": "Rozwiń {{depth}} poziomów", - "expand_all_levels": "Rozwiń wszystkie poziomy" + "expand_all_levels": "Rozwiń wszystkie poziomy", + "hide_child_notes": "Ukryj notatki podrzędne w derzwie" }, "board_view": { "move-to": "Przenieś do", @@ -240,7 +242,7 @@ "background_effects_title": "Efekty tła są teraz stabilne", "dismiss": "Odrzuć", "background_effects_button": "Włącz efekty tła", - "background_effects_message": "Na urządzeniach z systemem Windows efekty tła są teraz w pełni stabilne. Efekty tła dodają odrobinę koloru do interfejsu użytkownika poprzez rozmycie tła za nim. Ta technika jest również stosowana w innych aplikacjach, takich jak Eksplorator Windows.", + "background_effects_message": "Na urządzeniach z systemem Windows i macOS efekty tła są stabilne. Efekty tła dodają odrobinę koloru do interfejsu użytkownika poprzez rozmycie tła za nim.", "new_layout_title": "Nowy układ", "new_layout_message": "Wprowadziliśmy zmodernizowany układ interfejsu dla Trilium. Wstążka została usunięta i płynnie zintegrowana z głównym interfejsem, a jej kluczowe funkcje przejęły nowy pasek stanu i rozwijane sekcje (takie jak promowane atrybuty).\n\nNowy układ jest domyślnie włączony i można go tymczasowo wyłączyć w Ustawienia → Wygląd.", "new_layout_button": "Szczegóły" @@ -259,7 +261,6 @@ "percentage": "%" }, "pagination": { - "page_title": "Strona {{startIndex}} - {{endIndex}}", "total_notes": "{{count}} notatek" }, "collections": { @@ -520,7 +521,8 @@ "action": "akcja", "search_button": "Szukaj", "search_execute": "Szukaj i wykonaj akcje", - "view_options": "Ustawienia widoku:" + "view_options": "Ustawienia widoku:", + "option": "opcja" }, "similar_notes": { "title": "Podobne notatki", @@ -602,8 +604,8 @@ "desktop-application": "Aplikacja desktopowa", "native-title-bar": "Natywny pasek tytułu", "native-title-bar-description": "Dla Windows i macOS, wyłączenie natywnego paska tytułu sprawia, że aplikacja wygląda bardziej kompaktowo. Na Linuxie, włączenie natywnego paska tytułu lepiej integruje się z resztą systemu.", - "background-effects": "Włącz efekty tła (tylko Windows 11)", - "background-effects-description": "Efekt Mica dodaje rozmyte, stylowe tło do okien aplikacji, tworząc głębię i nowoczesny wygląd. \"Natywny pasek tytułu\" musi być wyłączony.", + "background-effects": "Włącz efekty tła", + "background-effects-description": "Dodaje rozmyte, stylowe tło do okien aplikacji, tworząc głębię i nowoczesny wygląd. \"Natywny pasek tytułu\" musi być wyłączony.", "restart-app-button": "Zrestartuj aplikację, aby zobaczyć zmiany", "zoom-factor": "Współczynnik powiększenia" }, @@ -1182,7 +1184,8 @@ "show-cheatsheet": "Pokaż ściągawkę", "toggle-zen-mode": "Tryb Zen", "new-version-available": "Dostępna nowa aktualizacja", - "download-update": "Pobierz wersję {{latestVersion}}" + "download-update": "Pobierz wersję {{latestVersion}}", + "search_notes": "Przeszukaj notatki" }, "zen_mode": { "button_exit": "Wyjdź z trybu Zen" @@ -1265,7 +1268,7 @@ "button_title": "Eksportuj diagram jako SVG" }, "relation_map_buttons": { - "create_child_note_title": "Utwórz nową notatkę podrzędną i dodaj ją do tej mapy relacji", + "create_child_note_title": "Utwórz notatkę podrzędną i dodaj ją do mapy", "reset_pan_zoom_title": "Zresetuj przesunięcie i powiększenie do początkowych współrzędnych i powiększenia", "zoom_in_title": "Powiększ", "zoom_out_title": "Pomniejsz" @@ -1281,12 +1284,23 @@ "delete_this_note": "Usuń tę notatkę", "note_revisions": "Wersje notatki", "error_cannot_get_branch_id": "Nie można pobrać branchId dla ścieżki notatki '{{notePath}}'", - "error_unrecognized_command": "Nierozpoznane polecenie {{command}}" + "error_unrecognized_command": "Nierozpoznane polecenie {{command}}", + "backlinks": "Linki zwrotne", + "content_language_switcher": "Język treści: {{language}}" }, "note_icon": { "change_note_icon": "Zmień ikonę notatki", "search": "Szukaj:", - "reset-default": "Przywróć domyślną ikonę" + "reset-default": "Przywróć domyślną ikonę", + "search_placeholder_one": "Znaleziono {{number}} ikonę w {{count}} pakietach", + "search_placeholder_few": "Znaleziono {{number}} ikon w {{count}} pakietach", + "search_placeholder_many": "Znaleziono {{number}} ikon w {{count}} pakietach", + "search_placeholder_filtered": "Wyszukaj {{number}} ikon w {{name}}", + "filter": "Filtr", + "filter-none": "Wszystkie ikony", + "filter-default": "Domyślne ikony", + "icon_tooltip": "{{name}}\npakiet ikon: {{iconPack}}", + "no_results": "Nie znaleziono ikon." }, "basic_properties": { "note_type": "Typ notatki", @@ -1417,15 +1431,6 @@ "default_new_note_title": "nowa notatka", "click_on_canvas_to_place_new_note": "Kliknij na płótnie, aby umieścić nową notatkę" }, - "render": { - "note_detail_render_help_1": "Ta notatka pomocy jest wyświetlana, ponieważ ta notatka typu Render HTML nie ma wymaganej relacji do poprawnego działania.", - "note_detail_render_help_2": "Typ notatki Render HTML jest używany do skryptowania. W skrócie, masz notatkę kodu HTML (opcjonalnie z JavaScript) i ta notatka ją wyrenderuje. Aby to zadziałało, musisz zdefiniować relację o nazwie \"renderNote\" wskazującą na notatkę HTML do wyrenderowania." - }, - "web_view": { - "web_view": "Widok WWW", - "embed_websites": "Notatka typu Widok WWW pozwala na osadzanie stron internetowych w Trilium.", - "create_label": "Aby rozpocząć, utwórz etykietę z adresem URL, który chcesz osadzić, np. #webViewSrc=\"https://www.google.com\"" - }, "backend_log": { "refresh": "Odśwież" }, @@ -1826,7 +1831,7 @@ "will_be_deleted_in": "Ten załącznik zostanie automatycznie usunięty za {{time}}", "will_be_deleted_soon": "Ten załącznik zostanie wkrótce automatycznie usunięty", "deletion_reason": ", ponieważ załącznik nie jest podlinkowany w treści notatki. Aby zapobiec usunięciu, dodaj link do załącznika z powrotem do treści lub przekonwertuj załącznik na notatkę.", - "role_and_size": "Rola: {{role}}, Rozmiar: {{size}}", + "role_and_size": "Rola: {{role}}, Rozmiar: {{size}}, MIME: {{- mimeType}}", "link_copied": "Link do załącznika skopiowany do schowka.", "unrecognized_role": "Nierozpoznana rola załącznika '{{role}}'." }, @@ -1880,7 +1885,10 @@ "apply-bulk-actions": "Zastosuj akcje masowe", "converted-to-attachments": "{{count}} notatek zostało przekonwertowanych na załączniki.", "convert-to-attachment-confirm": "Czy na pewno chcesz przekonwertować wybrane notatki na załączniki ich notatek nadrzędnych? Ta operacja dotyczy tylko notatek Obrazów, inne notatki zostaną pominięte.", - "open-in-popup": "Szybka edycja" + "open-in-popup": "Szybka edycja", + "open-in-a-new-window": "Otwórz w nowym oknie", + "hide-subtree": "Ukryj gałąź", + "show-subtree": "Rozwiń gałąź" }, "shared_info": { "shared_publicly": "Ta notatka jest udostępniona publicznie pod adresem {{- link}}.", @@ -1971,7 +1979,17 @@ "create-child-note": "Utwórz notatkę podrzędną", "unhoist": "Cofnij zawężenie", "toggle-sidebar": "Przełącz pasek boczny", - "dropping-not-allowed": "Upuszczanie notatek w tej lokalizacji jest niedozwolone." + "dropping-not-allowed": "Upuszczanie notatek w tej lokalizacji jest niedozwolone.", + "clone-indicator-tooltip": "Ta notatka ma {{- count}} notatek nadrzędnych: {{- parents}}", + "clone-indicator-tooltip-single": "Ta notatka jest sklonowana (1 dodatkowa notatka nadrzędna: {{- parent}})", + "shared-indicator-tooltip": "Ta notatka jest udostępniona publicznie", + "shared-indicator-tooltip-with-url": "Ta notatka jest udostępniana publicznie jako: {{- url}}", + "subtree-hidden-tooltip_one": "{{count}} notatka podrzędna ukryta w drzewie", + "subtree-hidden-tooltip_few": "{{count}} notatek podrzędnych ukrytych w drzewie", + "subtree-hidden-tooltip_many": "{{count}} notatek podrzędnych ukrytych w drzewie", + "subtree-hidden-moved-title": "Dodano do {{title}}", + "subtree-hidden-moved-description-collection": "Ta kolekcja ukrywa swoje notatki podrzędne w drzewie.", + "subtree-hidden-moved-description-other": "Notatki podrzędne są ukryte w drzewie tej notatki." }, "title_bar_buttons": { "window-on-top": "Utrzymuj okno na wierzchu" @@ -1979,7 +1997,13 @@ "note_detail": { "could_not_find_typewidget": "Nie można znaleźć widżetu typu dla typu '{{type}}'", "printing": "Drukowanie w toku...", - "printing_pdf": "Eksportowanie do PDF w toku..." + "printing_pdf": "Eksportowanie do PDF w toku...", + "print_report_title": "Wydrukuj raport", + "print_report_collection_content_one": "Nie można wydrukować {{count}} notatki w kolekcji, ponieważ nie jest ona obsługiwana lub jest chroniona.", + "print_report_collection_content_few": "Nie można wydrukować {{count}} notatek w kolekcji, ponieważ nie są one obsługiwane lub są chronione.", + "print_report_collection_content_many": "Nie można wydrukować {{count}} notatek w kolekcji, ponieważ nie są one obsługiwane lub są chronione.", + "print_report_collection_details_button": "Zobacz szczegóły", + "print_report_collection_details_ignored_notes": "Zignorowane notatki" }, "note_title": { "placeholder": "wpisz tytuł notatki tutaj...", @@ -1989,7 +2013,8 @@ "note_type_switcher_others": "Inny typ notatki", "note_type_switcher_templates": "Szablon", "note_type_switcher_collection": "Kolekcja", - "edited_notes": "Edytowane notatki" + "edited_notes": "Notatki edytowane dzisiaj", + "promoted_attributes": "Sugerowane atrybuty" }, "search_result": { "no_notes_found": "Nie znaleziono notatek dla podanych parametrów wyszukiwania.", @@ -1999,7 +2024,11 @@ "configure_launchbar": "Konfiguruj pasek szybkiego dostępu" }, "sql_result": { - "no_rows": "Dla tego zapytania nie zwrócono żadnych wierszy" + "no_rows": "Dla tego zapytania nie zwrócono żadnych wierszy", + "not_executed": "Zapytanie nie zostało jeszcze wykonane.", + "failed": "Wykonanie zapytania SQL nie powiodło się", + "statement_result": "Wynik wyrażenia", + "execute_now": "Wykonaj teraz" }, "sql_table_schemas": { "tables": "Tabele" @@ -2116,7 +2145,8 @@ "geo-map": { "create-child-note-title": "Utwórz nową notatkę podrzędną i dodaj ją do mapy", "create-child-note-instruction": "Kliknij na mapie, aby utworzyć nową notatkę w tej lokalizacji lub naciśnij Escape, aby anulować.", - "unable-to-load-map": "Nie można załadować mapy." + "unable-to-load-map": "Nie można załadować mapy.", + "create-child-note-text": "Dodaj zaznaczenie" }, "geo-map-context": { "open-location": "Otwórz lokalizację", @@ -2183,7 +2213,14 @@ "execute_sql_description": "Ta notatka jest notatką SQL. Kliknij, aby wykonać zapytanie SQL.", "shared_copy_to_clipboard": "Kopiuj link do schowka", "shared_open_in_browser": "Otwórz link w przeglądarce", - "shared_unshare": "Usuń udostępnienie" + "shared_unshare": "Usuń udostępnienie", + "save_status_saved": "Zapisane", + "save_status_saving": "Zapisywanie...", + "save_status_unsaved": "Niezapisane", + "save_status_error": "Zapis nie powiódł się", + "save_status_saving_tooltip": "Zmiany zostały zapisane.", + "save_status_unsaved_tooltip": "Są niezapisane zmiany. Zostaną one zapisane automatycznie za chwilę.", + "save_status_error_tooltip": "Wystąpił błąd podczas zapisywania notatki. Spróbuj skopiować treść notatki w inne miejsce i ponownie załadować aplikację." }, "status_bar": { "language_title": "Zmień język treści", @@ -2226,5 +2263,30 @@ "empty_button": "Ukryj panel", "toggle": "Pokaż/ukryj prawy panel", "custom_widget_go_to_source": "Przejdź do kodu źródłowego" + }, + "pdf": { + "attachments_one": "{{count}} załącznik", + "attachments_few": "{{count}} załączniki", + "attachments_many": "{{count}} załączników", + "layers_one": "{{count}} warstwa", + "layers_few": "{{count}} warstw", + "layers_many": "{{count}} warstw", + "pages_one": "{{count}} strona", + "pages_few": "{{count}} stron", + "pages_many": "{{count}} stron", + "pages_alt": "Strona {{pageNumber}}", + "pages_loading": "Wczytuję..." + }, + "platform_indicator": { + "available_on": "Dostępne na {{platform}}" + }, + "mobile_tab_switcher": { + "title_one": "{{count}} zakładka", + "title_few": "{{count}} zakładki", + "title_many": "{{count}} zakładek", + "more_options": "Więcej opcji" + }, + "bookmark_buttons": { + "bookmarks": "Zakładki" } } diff --git a/apps/client/src/translations/pt/translation.json b/apps/client/src/translations/pt/translation.json index cd03411ceb..7975182509 100644 --- a/apps/client/src/translations/pt/translation.json +++ b/apps/client/src/translations/pt/translation.json @@ -1064,15 +1064,6 @@ "default_new_note_title": "nova nota", "click_on_canvas_to_place_new_note": "Clique no quadro para incluir uma nova nota" }, - "render": { - "note_detail_render_help_1": "Esta nota de ajuda é mostrada porque esta nota do tipo Renderizar HTML não possui a relação necessária para funcionar corretamente.", - "note_detail_render_help_2": "O tipo de nota Renderizar HTML é usado para automação. Em suma, tem uma nota de código HTML (opcionalmente com algum JavaScript) e esta nota irá renderizá-la. Para fazê-lo funcionar, deve definir uma relação chamada \"renderNote\" que aponta para a nota HTML a ser renderizada." - }, - "web_view": { - "web_view": "Web View", - "embed_websites": "Nota do tipo Visualização Web permite que incorpore sites no Trilium.", - "create_label": "Para começar, crie uma etiqueta com um endereço URL que deseja incorporar, por exemplo, #webViewSrc=\"https://www.google.com\"" - }, "backend_log": { "refresh": "Recarregar" }, @@ -2174,7 +2165,6 @@ "delete_note": "Apagar nota..." }, "pagination": { - "page_title": "Página {{startIndex}} - {{endIndex}}", "total_notes": "{{count}} notas" }, "collections": { diff --git a/apps/client/src/translations/pt_br/translation.json b/apps/client/src/translations/pt_br/translation.json index cb628d931e..2c57dab23b 100644 --- a/apps/client/src/translations/pt_br/translation.json +++ b/apps/client/src/translations/pt_br/translation.json @@ -1271,11 +1271,6 @@ "start_dragging_relations": "Comece arrastando as relações daqui e solte-as em outra nota.", "cannot_match_transform": "Não foi possível combinar a transformação: {{transform}}" }, - "web_view": { - "web_view": "Web View", - "embed_websites": "Nota do tipo Visualização Web permite que você incorpore sites dentro do Trilium.", - "create_label": "Para começar, crie uma etiqueta com um endereço URL que deseja incorporar, por exemplo, #webViewSrc=\"https://www.google.com\"" - }, "backend_log": { "refresh": "Recarregar" }, @@ -1996,10 +1991,6 @@ "drag_locked_title": "Bloqueado para edição", "drag_locked_message": "Arrastar não é permitido pois a coleção está bloqueada para edição." }, - "render": { - "note_detail_render_help_1": "Esta nota de ajuda é mostrada porque esta nota do tipo Renderizar HTML não possui a relação necessária para funcionar corretamente.", - "note_detail_render_help_2": "O tipo de nota Renderizar HTML é usado para automação. Em suma, você tem uma nota de código HTML (opcionalmente com algum JavaScript) e esta nota irá renderizá-la. Para fazê-lo funcionar, você precisa definir uma relação chamada \"renderNote\" apontando para a nota HTML a ser renderizada." - }, "etapi": { "title": "ETAPI", "description": "ETAPI é uma API REST usada para acessar a instância do Trilium programaticamente, sem interface gráfica.", @@ -2124,7 +2115,6 @@ "shared_locally": "Esta nota é compartilhada localmente em {{- link}}." }, "pagination": { - "page_title": "Página de {{startIndex}} - {{endIndex}}", "total_notes": "{{count}} notas" }, "collections": { diff --git a/apps/client/src/translations/ro/translation.json b/apps/client/src/translations/ro/translation.json index 4823db67d3..e955dab73b 100644 --- a/apps/client/src/translations/ro/translation.json +++ b/apps/client/src/translations/ro/translation.json @@ -1094,10 +1094,6 @@ "rename_relation_from": "Redenumește relația din", "to": "În" }, - "render": { - "note_detail_render_help_1": "Această notă informativă este afișată deoarece această notiță de tip „Randare HTML” nu are relația necesară pentru a funcționa corespunzător.", - "note_detail_render_help_2": "Notița de tipul „Render HTML” este utilizată pentru scriptare. Pe scurt, se folosește o notiță de tip cod HTML (opțional cu niște JavaScript) și această notiță o va randa. Pentru a funcționa, trebuie definită o relație denumită „renderNote” ce indică notița HTML de randat." - }, "revisions": { "confirm_delete": "Doriți ștergerea acestei revizii?", "confirm_delete_all": "Doriți ștergerea tuturor reviziilor acestei notițe?", @@ -1376,11 +1372,6 @@ "enable_vim_keybindings": "Permite utilizarea combinațiilor de taste în stil Vim pentru notițele de tip cod (fără modul ex)", "use_vim_keybindings_in_code_notes": "Combinații de taste Vim" }, - "web_view": { - "create_label": "Pentru a începe, creați o etichetă cu adresa URL de încorporat, e.g. #webViewSrc=\"https://www.google.com\"", - "embed_websites": "Notițele de tip „Vizualizare web” permit încorporarea site-urilor web în Trilium.", - "web_view": "Vizualizare web" - }, "wrap_lines": { "enable_line_wrap": "Activează trecerea automată pe rândul următor (poate necesita o reîncărcare a interfeței pentru a avea efect)", "wrap_lines_in_code_notes": "Trecerea automată pe rândul următor în notițe de cod" @@ -1761,8 +1752,8 @@ "show-recent-notes": "Afișează notițele recente" }, "electron_integration": { - "background-effects": "Activează efectele de fundal (doar pentru Windows 11)", - "background-effects-description": "Efectul Mica adaugă un fundal estompat și elegant ferestrelor aplicațiilor, creând profunzime și un aspect modern. Opțiunea „Bară de titlu nativă” trebuie să fie dezactivată.", + "background-effects": "Activează efectele de fundal", + "background-effects-description": "Adaugă un fundal estompat și elegant ferestrelor aplicațiilor, creând profunzime și un aspect modern. Opțiunea „Bară de titlu nativă” trebuie să fie dezactivată.", "desktop-application": "Aplicația desktop", "native-title-bar": "Bară de titlu nativă", "native-title-bar-description": "Pentru Windows și macOS, dezactivarea bării de titlu native face aplicația să pară mai compactă. Pe Linux, păstrarea bării integrează mai bine aplicația cu restul sistemului de operare.", @@ -1781,7 +1772,8 @@ "geo-map": { "create-child-note-title": "Crează o notiță nouă și adaug-o pe hartă", "unable-to-load-map": "Nu s-a putut încărca harta.", - "create-child-note-instruction": "Click pe hartă pentru a crea o nouă notiță la acea poziție sau apăsați Escape pentru a anula." + "create-child-note-instruction": "Click pe hartă pentru a crea o nouă notiță la acea poziție sau apăsați Escape pentru a anula.", + "create-child-note-text": "Adaugă marcaj" }, "duration": { "days": "zile", @@ -2127,7 +2119,7 @@ }, "call_to_action": { "background_effects_title": "Efectele de fundal sunt acum stabile", - "background_effects_message": "Pe dispozitive cu Windows, efectele de fundal sunt complet stabile. Acestea adaugă un strop de culoare interfeței grafice prin estomparea fundalului din spatele ferestrei. Această tehnică este folosită și în alte aplicații precum Windows Explorer.", + "background_effects_message": "Pe dispozitive cu Windows și macOS, efectele de fundal sunt stabile. Acestea adaugă un strop de culoare interfeței grafice prin estomparea fundalului din spatele ferestrei.", "background_effects_button": "Activează efectele de fundal", "next_theme_title": "Încercați noua temă Trilium", "next_theme_message": "Utilizați tema clasică, doriți să încercați noua temă?", @@ -2159,7 +2151,6 @@ "percentage": "%" }, "pagination": { - "page_title": "Pagina pentru {{startIndex}} - {{endIndex}}", "total_notes": "{{count}} notițe" }, "collections": { @@ -2281,5 +2272,14 @@ "pages_other": "{{count}} de pagini", "pages_alt": "Pagina {{pageNumber}}", "pages_loading": "Încărcare..." + }, + "platform_indicator": { + "available_on": "Disponibil pe {{platform}}" + }, + "mobile_tab_switcher": { + "title_one": "{{count}} tab", + "title_few": "{{count}} taburi", + "title_other": "{{count}} de taburi", + "more_options": "Mai multe opțiuni" } } diff --git a/apps/client/src/translations/ru/translation.json b/apps/client/src/translations/ru/translation.json index ec5ec50166..aa495eb287 100644 --- a/apps/client/src/translations/ru/translation.json +++ b/apps/client/src/translations/ru/translation.json @@ -668,7 +668,8 @@ "geo-map": { "unable-to-load-map": "Не удалось загрузить карту.", "create-child-note-instruction": "Щелкните по карте, чтобы создать новую заметку в этом месте, или нажмите Escape, чтобы закрыть ее.", - "create-child-note-title": "Создать новую дочернюю заметку и добавить ее на карту" + "create-child-note-title": "Создать новую дочернюю заметку и добавить ее на карту", + "create-child-note-text": "Добавить маркер" }, "note_tooltip": { "quick-edit": "Быстрое редактирование", @@ -685,8 +686,8 @@ "electron_integration": { "zoom-factor": "Коэффициент масштабирования", "restart-app-button": "Применить изменения и перезапустить приложение", - "background-effects-description": "Эффект Mica добавляет размытый, стильный фон окнам приложений, создавая глубину и современный вид. Опция \"Системная строка заголовка\" должна быть отключена.", - "background-effects": "Включить фоновые эффекты (только Windows 11)", + "background-effects-description": "Добавляет размытый, стильный фон окнам приложений, создавая глубину и современный вид. Опция \"Системная строка заголовка\" должна быть отключена.", + "background-effects": "Включить фоновые эффекты", "native-title-bar-description": "В Windows и macOS отключение системной строки заголовка делает приложение более компактным. В Linux включение системной строки заголовка улучшает интеграцию с остальной частью системы.", "native-title-bar": "Системная панель заголовка", "desktop-application": "Десктопное приложение" @@ -776,7 +777,11 @@ "refresh-saved-search-results": "Обновить сохраненные результаты поиска", "automatically-collapse-notes-title": "Заметки будут свернуты после определенного периода бездействия, чтобы навести порядок в дереве.", "toggle-sidebar": "Переключить боковую панель", - "dropping-not-allowed": "Перетаскивание заметок в эту область не разрешено." + "dropping-not-allowed": "Перетаскивание заметок в эту область не разрешено.", + "shared-indicator-tooltip": "Эта заметка опубликована", + "shared-indicator-tooltip-with-url": "Эта заметка доступно публично по адресу: {{- url}}", + "subtree-hidden-moved-description-other": "В дереве, к которому относится эта заметка, скрыты дочерние заметки.", + "subtree-hidden-moved-description-collection": "Эта коллекция скрывает свои дочерние заметки в дереве." }, "quick-search": { "no-results": "Результаты не найдены", @@ -856,7 +861,10 @@ "convert-to-attachment-confirm": "Вы уверены, что хотите преобразовать выбранные заметки во вложения их родительских заметок? Эта операция применяется только к заметкам в виде изображений; другие заметки будут пропущены.", "converted-to-attachments": "{{count}} заметок были преобразованы во вложения.", "archive": "Архивировать", - "unarchive": "Разархивировать" + "unarchive": "Разархивировать", + "open-in-a-new-window": "Открыть в новом окне", + "hide-subtree": "Скрыть поддерево", + "show-subtree": "Показать поддерево" }, "info": { "closeButton": "Закрыть", @@ -1000,7 +1008,8 @@ "switch_to_mobile_version": "Перейти на мобильную версию", "switch_to_desktop_version": "Переключиться на версию для ПК", "new-version-available": "Доступно обновление", - "download-update": "Обновить до {{latestVersion}}" + "download-update": "Обновить до {{latestVersion}}", + "search_notes": "Поиск заметок" }, "zpetne_odkazy": { "relation": "отношение", @@ -1047,7 +1056,8 @@ "expand_all_levels": "Развернуть все вложенные уровни", "expand_nth_level": "Развернуть уровни: {{depth}} шт.", "expand_first_level": "Развернуть прямые дочерние уровни", - "expand_tooltip": "Разщвернуть дочерние элементы этой коллекции (на один уровень вложенности). Для получения дополнительных параметров нажмите стрелку справа." + "expand_tooltip": "Разщвернуть дочерние элементы этой коллекции (на один уровень вложенности). Для получения дополнительных параметров нажмите стрелку справа.", + "hide_child_notes": "Скрыть дочерние заметки в дереве" }, "edited_notes": { "deleted": "(удалено)", @@ -1692,7 +1702,7 @@ "zoom_in_title": "Увеличить масштаб", "zoom_out_title": "Уменьшить масштаб", "reset_pan_zoom_title": "Сбросить панорамирование и масштабирование", - "create_child_note_title": "Создать новую дочернюю заметку и добавить ее в эту карту связей" + "create_child_note_title": "Создать дочернюю заметку и добавить ее в карту" }, "code_auto_read_only_size": { "unit": "символов", @@ -1845,7 +1855,8 @@ "error_cannot_get_branch_id": "Невозможно получить branchId для notePath '{{notePath}}'", "delete_this_note": "Удалить эту заметку", "insert_child_note": "Вставить дочернюю заметку", - "note_revisions": "История изменений" + "note_revisions": "История изменений", + "content_language_switcher": "Язык содержимого: {{language}}" }, "svg_export_button": { "button_title": "Экспортировать диаграмму как SVG" @@ -1900,7 +1911,7 @@ "dismiss": "Отклонить", "background_effects_button": "Включить эффекты фона", "next_theme_button": "Попробовать новую тему", - "background_effects_message": "На устройствах Windows фоновые эффекты теперь полностью стабильны. Они добавляют цвет в пользовательский интерфейс, размывая фон за ним. Этот приём также используется в других приложениях, например, в проводнике Windows.", + "background_effects_message": "На устройствах с ОС Windows или macOS, фоновые эффекты теперь полностью стабильны. Они добавляют цвета в пользовательский интерфейс, размывая фон за ним.", "background_effects_title": "Фоновые эффекты теперь стабильны", "next_theme_title": "Попробуйте новую тему Trilium", "new_layout_button": "Подробнее", @@ -1988,11 +1999,6 @@ "attachment_deleted": "Это вложение было удалено.", "you_can_also_open": ", вы также можете открыть " }, - "web_view": { - "web_view": "Веб-страница", - "create_label": "Для начала создайте метку с URL-адресом, который вы хотите встроить, например, #webViewSrc=\"https://www.google.com\"", - "embed_websites": "Заметки типа \"Веб-страница\" позволяет встраивать веб-сайты в Trilium." - }, "ribbon": { "widgets": "Виджеты ленты", "promoted_attributes_message": "Вкладка \"Продвигаемые атрибуты\" будет автоматически открыта, если таковые атрибуты установлены у заметки", @@ -2075,10 +2081,6 @@ "help-button": { "title": "Открыть соответствующую страницу справки" }, - "render": { - "note_detail_render_help_2": "Тип заметки «Рендер HTML» используется для скриптинга. Если коротко, у вас есть заметка с HTML-кодом (возможно, с добавлением JavaScript), и эта заметка её отобразит. Для этого необходимо определить отношение с именем «renderNote», указывающее на HTML-заметку для отрисовки.", - "note_detail_render_help_1": "Эта справочная заметка отображается, поскольку эта справка типа Render HTML не имеет необходимой связи для правильной работы." - }, "file": { "too_big": "В целях повышения производительности в режиме предварительного просмотра отображаются только первые {{maxNumChars}} символов файла. Загрузите файл и откройте его во внешнем браузере, чтобы увидеть всё содержимое.", "file_preview_not_available": "Предварительный просмотр файла недоступен для этого файла." @@ -2094,7 +2096,11 @@ "ui": "Пользовательский интерфейс" }, "sql_result": { - "no_rows": "По этому запросу не возвращено ни одной строки" + "no_rows": "По этому запросу не возвращено ни одной строки", + "not_executed": "Запрос еще не выполнен.", + "failed": "Выполнение SQL-запроса завершилось с ошибкой", + "statement_result": "Результат заявления", + "execute_now": "Выполнить сейчас" }, "editable_code": { "placeholder": "Введите содержимое для заметки с кодом..." @@ -2144,8 +2150,7 @@ "rendering_error": "Невозможно отобразить содержимое из-за ошибки." }, "pagination": { - "total_notes": "{{count}} заметок", - "page_title": "Страница {{startIndex}} - {{endIndex}}" + "total_notes": "{{count}} заметок" }, "status_bar": { "attributes_one": "{{count}} атрибут", @@ -2189,7 +2194,14 @@ "read_only_auto_description": "Эта заметка была автоматически переведена в режим только для чтения по соображениям производительности. Это автоматическое ограничение можно изменить в настройках.\n\nНажмите, чтобы временно отредактировать её.", "read_only_auto": "Автоматический режим \"только для чтения\"", "read_only_explicit_description": "Эта заметка была вручную установлена в режим «только для чтения».\nНажмите, чтобы временно отредактировать её.", - "read_only_explicit": "Только для чтения" + "read_only_explicit": "Только для чтения", + "save_status_saving": "Сохранение...", + "save_status_saved": "Сохранение", + "save_status_unsaved": "Не сохранено", + "save_status_error": "Ошибка сохранения", + "save_status_saving_tooltip": "Изменения сохраняются.", + "save_status_unsaved_tooltip": "Есть несохраненные изменения. Они будут сохранены автоматически через некоторое время.", + "save_status_error_tooltip": "Произошла ошибка при сохранении заметки. Если возможно, попробуйте скопировать содержимое заметки в другое место и перезагрузить приложение." }, "breadcrumb": { "hoisted_badge_title": "Снять фокус", @@ -2243,5 +2255,30 @@ }, "attributes_panel": { "title": "Атрибуты заметки" + }, + "bookmark_buttons": { + "bookmarks": "Закладки" + }, + "mobile_tab_switcher": { + "more_options": "Показать больше", + "title_one": "{{count}} вкладка", + "title_few": "{{count}} вкладки", + "title_many": "{{count}} вкладок" + }, + "pdf": { + "pages_loading": "Загрузка...", + "pages_alt": "Страница {{pageNumber}}", + "pages_one": "{{count}} страница", + "pages_few": "{{count}} страницы", + "pages_many": "{{count}} страниц", + "layers_one": "{{count}} слой", + "layers_few": "{{count}} слоя", + "layers_many": "{{count}} слоев", + "attachments_one": "{{count}} вложение", + "attachments_few": "{{count}} вложения", + "attachments_many": "{{count}} вложений" + }, + "platform_indicator": { + "available_on": "Доступно для {{platform}}" } } diff --git a/apps/client/src/translations/tw/translation.json b/apps/client/src/translations/tw/translation.json index d4ef14f53a..39d2f73d60 100644 --- a/apps/client/src/translations/tw/translation.json +++ b/apps/client/src/translations/tw/translation.json @@ -662,7 +662,8 @@ "show-cheatsheet": "顯示快捷鍵說明", "toggle-zen-mode": "禪模式", "new-version-available": "發現新更新", - "download-update": "取得版本 {{latestVersion}}" + "download-update": "取得版本 {{latestVersion}}", + "search_notes": "搜尋筆記" }, "sync_status": { "unknown": "

同步狀態將在下一次同步嘗試開始後顯示。

點擊以立即觸發同步。

", @@ -757,7 +758,9 @@ "delete_this_note": "刪除此筆記", "error_cannot_get_branch_id": "無法獲取 notePath '{{notePath}}' 的 branchId", "error_unrecognized_command": "無法識別的命令 {{command}}", - "note_revisions": "筆記歷史版本" + "note_revisions": "筆記歷史版本", + "backlinks": "反向連結", + "content_language_switcher": "內文語言:{{language}}" }, "note_icon": { "change_note_icon": "更改筆記圖標", @@ -909,7 +912,8 @@ "unknown_search_option": "未知的搜尋選項 {{searchOptionName}}", "search_note_saved": "搜尋筆記已儲存至 {{- notePathTitle}}", "actions_executed": "已執行操作。", - "view_options": "查看選項:" + "view_options": "查看選項:", + "option": "選項" }, "similar_notes": { "title": "相似筆記", @@ -1003,7 +1007,7 @@ "no_attachments": "此筆記沒有附件。" }, "book": { - "no_children_help": "此類型為書籍的筆記沒有任何子筆記,因此沒有內容可顯示。請參閱 wiki 以了解詳情。", + "no_children_help": "此集合沒有任何子筆記,因此沒有內容可顯示。", "drag_locked_title": "鎖定編輯", "drag_locked_message": "無法拖曳,因為此集合已被鎖定編輯。" }, @@ -1059,15 +1063,6 @@ "default_new_note_title": "新筆記", "click_on_canvas_to_place_new_note": "點擊畫布以放置新筆記" }, - "render": { - "note_detail_render_help_1": "之所以顯示此說明筆記,是因為該類型的渲染 HTML 沒有設定好必須的關聯。", - "note_detail_render_help_2": "渲染筆記類型用於編寫 腳本。簡單說就是您可以寫HTML程式碼(或者加上一些JavaScript程式碼), 然後這個筆記會把頁面渲染出來。要使其正常工作,您需要定義一個名為 \"renderNote\" 的 關聯 指向要呈現的 HTML 筆記。" - }, - "web_view": { - "web_view": "網頁顯示", - "embed_websites": "網頁顯示類型的筆記允許您將網站嵌入至 Trilium 中。", - "create_label": "首先,請新增一個帶有您要嵌入的 URL 地址的標籤,例如 #webViewSrc=\"https://www.bing.com\"" - }, "backend_log": { "refresh": "重新整理" }, @@ -1378,7 +1373,8 @@ "description": "描述", "reload_app": "重新載入應用以套用更改", "set_all_to_default": "將所有快捷鍵重設為預設值", - "confirm_reset": "您確定要將所有鍵盤快捷鍵重設為預設值嗎?" + "confirm_reset": "您確定要將所有鍵盤快捷鍵重設為預設值嗎?", + "no_results": "未找到符合 '{{filter}}' 的捷徑" }, "spellcheck": { "title": "拼寫檢查", @@ -1582,7 +1578,9 @@ "print_report_collection_content_one": "集合中的 {{count}} 篇筆記無法列印,因為它們不被支援或受到保護。", "print_report_collection_content_other": "", "print_report_collection_details_button": "查看詳情", - "print_report_collection_details_ignored_notes": "忽略的筆記" + "print_report_collection_details_ignored_notes": "忽略的筆記", + "print_report_error_title": "列印失敗", + "print_report_stack_trace": "堆棧追蹤" }, "note_title": { "placeholder": "請輸入筆記標題...", @@ -1939,8 +1937,8 @@ "desktop-application": "桌面版應用程式", "native-title-bar": "原生標題列", "native-title-bar-description": "對於 Windows 和 macOS,關閉原生標題列會讓應用程式看起來更緊湊。在 Linux 上,開啟原生標題列可以與系統的其他部分整合得更好。", - "background-effects": "啟用背景效果(僅適用於 Windows 11)", - "background-effects-description": "Mica 效果為程式視窗新增模糊且時尚的背景,營造出深度感和現代化外觀。「原生標題列」必須被禁用。", + "background-effects": "啟用背景效果", + "background-effects-description": "為程式視窗新增模糊且時尚的背景,營造立體感和現代化外觀。「原生標題列」必須被禁用。", "restart-app-button": "重新啟動應用程式以查看更改", "zoom-factor": "縮放係數" }, @@ -1959,7 +1957,8 @@ "geo-map": { "create-child-note-title": "建立一個新的子筆記並將其加至地圖中", "create-child-note-instruction": "點擊地圖以在該位置建立新筆記,或按 Escape 以取消。", - "unable-to-load-map": "無法載入地圖。" + "unable-to-load-map": "無法載入地圖。", + "create-child-note-text": "新增地圖標記" }, "geo-map-context": { "open-location": "打開位置", @@ -2075,7 +2074,8 @@ "raster": "柵格", "vector_light": "向量(淺色)", "vector_dark": "向量(深色)", - "show-scale": "顯示比例尺" + "show-scale": "顯示比例尺", + "show-labels": "顯示標記名稱" }, "table_context_menu": { "delete_row": "刪除列" @@ -2122,7 +2122,7 @@ }, "call_to_action": { "background_effects_title": "背景特效已推出穩定版本", - "background_effects_message": "在 Windows 裝置上,背景特效現在已完全穩定。背景特效透過模糊背後的背景,為使用者介面增添一抹色彩。此技術也用於其他應用程式,例如 Windows 檔案總管。", + "background_effects_message": "在 Windows 和macOS裝置上,背景特效現在已穩定。背景特效透過模糊背後的背景,為使用者介面增添一抹色彩。", "background_effects_button": "啟用背景特效", "next_theme_title": "試用新 Trilium 主題", "next_theme_message": "您正在使用舊版主題,要試用新主題嗎?", @@ -2154,7 +2154,6 @@ "app-restart-required": "(需要重啟程式以套用更改)" }, "pagination": { - "page_title": "第 {{startIndex}} - {{endIndex}} 頁", "total_notes": "{{count}} 筆記" }, "collections": { @@ -2267,5 +2266,60 @@ "pages_other": "", "pages_alt": "第 {{pageNumber}} 頁", "pages_loading": "正在載入…" + }, + "mobile_tab_switcher": { + "more_options": "更多選項", + "title_one": "{{count}} 個分頁", + "title_other": "" + }, + "platform_indicator": { + "available_on": "可於 {{platform}} 使用" + }, + "bookmark_buttons": { + "bookmarks": "書籤" + }, + "render": { + "setup_title": "在此筆記中顯示自訂 HTML 或 Preact JSX", + "setup_create_sample_preact": "使用 Preact 建立範例筆記", + "setup_create_sample_html": "使用 HTML 建立範例筆記", + "setup_sample_created": "已建立一個範例筆記作為子筆記。", + "disabled_description": "此渲染筆記來自外部來源。為保護您免受惡意內容侵害,此功能預設為停用狀態。啟用前請務必確認來源可信。", + "disabled_button_enable": "啟用渲染筆記" + }, + "web_view_setup": { + "title": "將網頁直接匯入 Trilium 建立即時預覽", + "url_placeholder": "輸入或貼上網站網址,例如 https://triliumnotes.org", + "create_button": "建立網頁檢視", + "invalid_url_title": "無效地址", + "invalid_url_message": "請輸入有效的網址,例如 https://triliumnotes.org。", + "disabled_description": "此網頁檢視來自外部來源。為協助保護您免受網路釣魚或惡意內容侵害,內容不會自動載入。若您信任來源,可手動啟用此功能。", + "disabled_button_enable": "啟用網頁檢視" + }, + "active_content_badges": { + "type_icon_pack": "圖示包", + "type_backend_script": "後端腳本", + "type_frontend_script": "前端腳本", + "type_widget": "元件", + "type_app_css": "自訂 CSS", + "type_render_note": "渲染筆記", + "type_web_view": "網頁顯示", + "type_app_theme": "自訂主題", + "toggle_tooltip_enable_tooltip": "點擊以啟用此 {{type}}。", + "toggle_tooltip_disable_tooltip": "點擊以停用此 {{type}}。", + "menu_docs": "打開文件", + "menu_execute_now": "立即執行腳本", + "menu_run": "自動執行", + "menu_run_disabled": "手動", + "menu_run_backend_startup": "當後端啟動時", + "menu_run_hourly": "每小時", + "menu_run_daily": "每日", + "menu_run_frontend_startup": "當桌面前端啟動時", + "menu_run_mobile_startup": "當移動前端啟動時", + "menu_change_to_widget": "更改為元件", + "menu_change_to_frontend_script": "更改為前端腳本", + "menu_theme_base": "主題基底" + }, + "setup_form": { + "more_info": "了解更多" } } diff --git a/apps/client/src/translations/uk/translation.json b/apps/client/src/translations/uk/translation.json index 3d0614fdfe..c2c8a5588d 100644 --- a/apps/client/src/translations/uk/translation.json +++ b/apps/client/src/translations/uk/translation.json @@ -1130,15 +1130,6 @@ "default_new_note_title": "нова нотатка", "click_on_canvas_to_place_new_note": "Натисніть на полотно, щоб розмістити нову нотатку" }, - "render": { - "note_detail_render_help_1": "Ця довідка відображається, оскільки ця нотатка типу Render HTML не має необхідного зв'язку для належного функціонування.", - "note_detail_render_help_2": "Тип нотатки Render HTML використовується для скриптів. Коротше кажучи, у вас є нотатка з HTML-кодом (за бажанням з деяким JavaScript), і ця нотатка її відобразить. Щоб це запрацювало, вам потрібно визначити відношення під назвою \"renderNote\", яке вказує на нотатку HTML для відображення." - }, - "web_view": { - "web_view": "Веб-перегляд", - "embed_websites": "Нотатка типу Веб-перегляд дозволяє вбудовувати веб-сайти в Trilium.", - "create_label": "Для початку створіть мітку з URL-адресою, яку ви хочете вбудувати, наприклад, #webViewSrc=\"https://www.google.com\"" - }, "backend_log": { "refresh": "Оновити" }, @@ -2072,7 +2063,6 @@ "app-restart-required": "(щоб зміни набули чинності, потрібен перезапуск програми)" }, "pagination": { - "page_title": "Сторінка {{startIndex}} - {{endIndex}}", "total_notes": "{{count}} нотаток" }, "collections": { diff --git a/apps/client/src/types-lib.d.ts b/apps/client/src/types-lib.d.ts index aa125f389d..4f942b8cb6 100644 --- a/apps/client/src/types-lib.d.ts +++ b/apps/client/src/types-lib.d.ts @@ -63,11 +63,13 @@ declare global { declare module "preact" { namespace JSX { + interface ElectronWebViewElement extends JSX.HTMLAttributes { + src: string; + class: string; + } + interface IntrinsicElements { - webview: { - src: string; - class: string; - } + webview: ElectronWebViewElement; } } } diff --git a/apps/client/src/types.d.ts b/apps/client/src/types.d.ts index 2e2a36e6ee..f7673901c1 100644 --- a/apps/client/src/types.d.ts +++ b/apps/client/src/types.d.ts @@ -119,7 +119,7 @@ declare global { setNote(noteId: string); } - var logError: (message: string, e?: Error | string) => void; + var logError: (message: string, e?: unknown) => void; var logInfo: (message: string) => void; var glob: CustomGlobals; //@ts-ignore diff --git a/apps/client/src/widgets/Backlinks.css b/apps/client/src/widgets/Backlinks.css new file mode 100644 index 0000000000..9e8ced45ba --- /dev/null +++ b/apps/client/src/widgets/Backlinks.css @@ -0,0 +1,83 @@ +.tn-backlinks-widget .backlinks-items { + list-style-type: none; + margin: 0; + padding: 0; + position: static; + width: unset; + + > li { + --border-radius: 8px; + + max-width: 600px; + padding: 10px 20px; + background: var(--card-background-color); + + & + li { + margin-top: 2px; + } + + &:first-child { + border-radius: var(--border-radius) var(--border-radius) 0 0; + } + + &:last-child { + border-radius: 0 0 var(--border-radius) var(--border-radius); + } + + /* Card header */ + & > span:first-child { + display: block; + + > span { + display: flex; + flex-wrap: wrap; + align-items: center; + + /* Note path */ + > small { + flex: 100%; + order: -1; + font-size: .65rem; + + .note-path { + padding: 0; + } + } + + /* Note icon */ + > .tn-icon { + color: var(--menu-item-icon-color); + } + + /* Note title */ + > a { + margin-inline-start: 4px; + color: currentColor; + font-weight: 500; + } + } + } + + /* Card content - excerpt */ + .backlink-excerpt { + all: unset; /* TODO: Remove after disposing the old style from FloatingButtons.css */ + display: block; + + margin: 8px 0; + border-radius: 4px; + background: var(--quick-search-result-content-background); + padding: 8px; + font-size: .75rem; + + a { + background: transparent; + color: var(--quick-search-result-highlight-color); + text-decoration: underline; + } + + p { + margin: 0; + } + } + } +} diff --git a/apps/client/src/widgets/FloatingButtonsDefinitions.tsx b/apps/client/src/widgets/FloatingButtonsDefinitions.tsx index be8a41c46c..5d19389cf1 100644 --- a/apps/client/src/widgets/FloatingButtonsDefinitions.tsx +++ b/apps/client/src/widgets/FloatingButtonsDefinitions.tsx @@ -1,3 +1,5 @@ +import "./Backlinks.css"; + import { BacklinkCountResponse, BacklinksResponse, SaveSqlConsoleResponse } from "@triliumnext/commons"; import { VNode } from "preact"; import { useCallback, useEffect, useLayoutEffect, useRef, useState } from "preact/hooks"; @@ -60,14 +62,6 @@ export const DESKTOP_FLOATING_BUTTONS: FloatingButtonsList = [ Backlinks ]; -export const MOBILE_FLOATING_BUTTONS: FloatingButtonsList = [ - RefreshBackendLogButton, - EditButton, - RelationMapButtons, - ExportImageButtons, - Backlinks -]; - /** * Floating buttons that should be hidden in popup editor (Quick edit). */ diff --git a/apps/client/src/widgets/NoteDetail.css b/apps/client/src/widgets/NoteDetail.css index 4382277805..b07c6aa061 100644 --- a/apps/client/src/widgets/NoteDetail.css +++ b/apps/client/src/widgets/NoteDetail.css @@ -3,6 +3,30 @@ font-family: var(--detail-font-family); font-size: var(--detail-font-size); contain: none; + + &.fixed-tree { + display: flex; + flex-direction: column; + height: 100%; + + .fixed-note-tree-container { + height: 60%; + border-bottom: 1px solid var(--main-border-color); + overflow: auto; + + .tree-wrapper { + padding: 0; + } + + .tree { + padding: 0; + } + + ul { + margin: 0; + } + } + } } body.prefers-centered-content .note-detail { @@ -12,4 +36,4 @@ body.prefers-centered-content .note-detail { .note-detail > * { contain: none; -} \ No newline at end of file +} diff --git a/apps/client/src/widgets/NoteDetail.tsx b/apps/client/src/widgets/NoteDetail.tsx index 64a485188e..1b2cc8f8cc 100644 --- a/apps/client/src/widgets/NoteDetail.tsx +++ b/apps/client/src/widgets/NoteDetail.tsx @@ -1,5 +1,7 @@ import "./NoteDetail.css"; +import clsx from "clsx"; +import { note } from "mermaid/dist/rendering-util/rendering-elements/shapes/note.js"; import { isValidElement, VNode } from "preact"; import { useEffect, useRef, useState } from "preact/hooks"; @@ -12,8 +14,9 @@ import { t } from "../services/i18n"; import protected_session_holder from "../services/protected_session_holder"; import toast from "../services/toast.js"; import { dynamicRequire, isElectron, isMobile } from "../services/utils"; +import NoteTreeWidget from "./note_tree"; import { ExtendedNoteType, TYPE_MAPPINGS, TypeWidget } from "./note_types"; -import { useNoteContext, useTriliumEvent } from "./react/hooks"; +import { useLegacyWidget, useNoteContext, useTriliumEvent } from "./react/hooks"; import { NoteListWithLinks } from "./react/NoteList"; import { TypeWidgetProps } from "./type_widgets/type_widget"; @@ -36,6 +39,7 @@ export default function NoteDetail() { const [ noteTypesToRender, setNoteTypesToRender ] = useState<{ [ key in ExtendedNoteType ]?: (props: TypeWidgetProps) => VNode }>({}); const [ activeNoteType, setActiveNoteType ] = useState(); const widgetRequestId = useRef(0); + const hasFixedTree = note && noteContext?.hoistedNoteId === "_lbMobileRoot" && isMobile() && note.noteId.startsWith("_lbMobile"); const props: TypeWidgetProps = { note: note!, @@ -119,13 +123,6 @@ export default function NoteDetail() { } }); - // Fixed tree for launch bar config on mobile. - useEffect(() => { - if (!isMobile) return; - const hasFixedTree = noteContext?.hoistedNoteId === "_lbMobileRoot"; - document.body.classList.toggle("force-fixed-tree", hasFixedTree); - }, [ note ]); - // Handle toast notifications. useEffect(() => { if (!isElectron()) return; @@ -215,8 +212,13 @@ export default function NoteDetail() { return (
+ {hasFixedTree && } + {Object.entries(noteTypesToRender).map(([ itemType, Element ]) => { return new NoteTreeWidget(), { noteContext }); + return
{treeEl}
; +} + /** * Wraps a single note type widget, in order to keep it in the DOM even after the user has switched away to another note type. This allows faster loading of the same note type again. The properties are cached, so that they are updated only * while the widget is visible, to avoid rendering in the background. When not visible, the DOM element is simply hidden. @@ -349,6 +356,14 @@ export function checkFullHeight(noteContext: NoteContext | undefined, type: Exte // https://github.com/zadam/trilium/issues/2522 const isBackendNote = noteContext?.noteId === "_backendLog"; const isFullHeightNoteType = type && TYPE_MAPPINGS[type].isFullHeight; + + // Allow vertical centering when there are no results. + if (type === "book" && + [ "grid", "list" ].includes(noteContext.note?.getLabelValue("viewType") ?? "grid") && + !noteContext.note?.hasChildren()) { + return true; + } + return (!noteContext?.hasNoteList() && isFullHeightNoteType) || noteContext?.viewScope?.viewMode === "attachments" || isBackendNote; @@ -364,7 +379,33 @@ function showToast(type: "printing" | "exporting_pdf", progress: number = 0) { } function handlePrintReport(printReport?: PrintReport) { - if (printReport?.type === "collection" && printReport.ignoredNoteIds.length > 0) { + if (!printReport) return; + + if (printReport.type === "error") { + toast.showPersistent({ + id: "print-error", + icon: "bx bx-error-circle", + title: t("note_detail.print_report_error_title"), + message: printReport.message, + buttons: printReport.stack ? [ + { + text: t("note_detail.print_report_collection_details_button"), + onClick(api) { + api.dismissToast(); + dialog.info(<> +

{printReport.message}

+
+ {t("note_detail.print_report_stack_trace")} +
{printReport.stack}
+
+ , { + title: t("note_detail.print_report_error_title") + }); + } + } + ] : undefined + }); + } else if (printReport.type === "collection" && printReport.ignoredNoteIds.length > 0) { toast.showPersistent({ id: "print-report", icon: "bx bx-collection", diff --git a/apps/client/src/widgets/PromotedAttributes.css b/apps/client/src/widgets/PromotedAttributes.css index 6e3c7795d1..ef15905192 100644 --- a/apps/client/src/widgets/PromotedAttributes.css +++ b/apps/client/src/widgets/PromotedAttributes.css @@ -16,6 +16,10 @@ body.mobile .promoted-attributes-widget { display: table; } +body.experimental-feature-new-layout .promoted-attributes-container { + max-height: unset; +} + .promoted-attribute-cell { display: flex; align-items: center; @@ -94,4 +98,4 @@ body.mobile .promoted-attributes-widget { background: rgba(0, 0, 0, 0.5); transform: rotate(45deg); pointer-events: none; -} \ No newline at end of file +} diff --git a/apps/client/src/widgets/PromotedAttributes.tsx b/apps/client/src/widgets/PromotedAttributes.tsx index a9618d3a63..cbe5737256 100644 --- a/apps/client/src/widgets/PromotedAttributes.tsx +++ b/apps/client/src/widgets/PromotedAttributes.tsx @@ -5,6 +5,7 @@ import clsx from "clsx"; import { ComponentChild, HTMLInputTypeAttribute, InputHTMLAttributes, MouseEventHandler, TargetedEvent, TargetedInputEvent } from "preact"; import { Dispatch, StateUpdater, useEffect, useRef, useState } from "preact/hooks"; +import NoteContext from "../components/note_context"; import FAttribute from "../entities/fattribute"; import FNote from "../entities/fnote"; import { Attribute } from "../services/attribute_parser"; @@ -40,8 +41,8 @@ type OnChangeEventData = TargetedEvent | InputEvent | J type OnChangeListener = (e: OnChangeEventData) => Promise; export default function PromotedAttributes() { - const { note, componentId } = useNoteContext(); - const [ cells, setCells ] = usePromotedAttributeData(note, componentId); + const { note, componentId, noteContext } = useNoteContext(); + const [ cells, setCells ] = usePromotedAttributeData(note, componentId, noteContext); return ; } @@ -74,12 +75,12 @@ export function PromotedAttributesContent({ note, componentId, cells, setCells } * * The cells are returned as a state since they can also be altered internally if needed, for example to add a new empty cell. */ -export function usePromotedAttributeData(note: FNote | null | undefined, componentId: string): [ Cell[] | undefined, Dispatch> ] { +export function usePromotedAttributeData(note: FNote | null | undefined, componentId: string, noteContext: NoteContext | undefined): [ Cell[] | undefined, Dispatch> ] { const [ viewType ] = useNoteLabel(note, "viewType"); const [ cells, setCells ] = useState(); function refresh() { - if (!note || viewType === "table") { + if (!note || viewType === "table" || noteContext?.viewScope?.viewMode !== "default") { setCells([]); return; } @@ -124,7 +125,7 @@ export function usePromotedAttributeData(note: FNote | null | undefined, compone setCells(cells); } - useEffect(refresh, [ note, viewType ]); + useEffect(refresh, [ note, viewType, noteContext ]); useTriliumEvent("entitiesReloaded", ({ loadResults }) => { if (loadResults.getAttributeRows(componentId).find((attr) => attributes.isAffecting(attr, note))) { refresh(); diff --git a/apps/client/src/widgets/buttons/global_menu.tsx b/apps/client/src/widgets/buttons/global_menu.tsx index 255cf89c9f..25f48c5db2 100644 --- a/apps/client/src/widgets/buttons/global_menu.tsx +++ b/apps/client/src/widgets/buttons/global_menu.tsx @@ -29,7 +29,6 @@ export default function GlobalMenu({ isHorizontalLayout }: { isHorizontalLayout: const isVerticalLayout = !isHorizontalLayout; const parentComponent = useContext(ParentComponent); const { isUpdateAvailable, latestVersion } = useTriliumUpdateStatus(); - const isMobileLocal = isMobile(); const logoRef = useRef(null); useStaticTooltip(logoRef); @@ -44,9 +43,13 @@ export default function GlobalMenu({ isHorizontalLayout }: { isHorizontalLayout:
} } noDropdownListStyle - onShown={isMobileLocal ? () => document.getElementById("context-menu-cover")?.classList.add("show", "global-menu-cover") : undefined} - onHidden={isMobileLocal ? () => document.getElementById("context-menu-cover")?.classList.remove("show", "global-menu-cover") : undefined} + mobileBackdrop > + {isMobile() && <> + + + + } @@ -107,8 +110,7 @@ function BrowserOnlyOptions() { function DevelopmentOptions({ dropStart }: { dropStart: boolean }) { return <> - - Development Options + {experimentalFeatures.map((feature) => ( diff --git a/apps/client/src/widgets/collections/NoteList.css b/apps/client/src/widgets/collections/NoteList.css index 449f45d97c..d312f6a427 100644 --- a/apps/client/src/widgets/collections/NoteList.css +++ b/apps/client/src/widgets/collections/NoteList.css @@ -2,8 +2,12 @@ min-height: 0; max-width: var(--max-content-width); /* Inherited from .note-split */ - overflow: auto; + overflow: visible; contain: none !important; + + &.full-height { + overflow: auto; + } } body.prefers-centered-content .note-list-widget:not(.full-height) { @@ -19,14 +23,3 @@ body.prefers-centered-content .note-list-widget:not(.full-height) { .note-list-widget video { height: 100%; } - -/* #region Pagination */ -.note-list-pager { - font-size: 1rem; - - span.current-page { - text-decoration: underline; - font-weight: bold; - } -} -/* #endregion */ diff --git a/apps/client/src/widgets/collections/Pagination.css b/apps/client/src/widgets/collections/Pagination.css new file mode 100644 index 0000000000..93ee13a76d --- /dev/null +++ b/apps/client/src/widgets/collections/Pagination.css @@ -0,0 +1,88 @@ +:where(.note-list-pager) { + --note-list-pager-page-button-width: 40px; + --note-list-pager-page-button-gap: 3px; + --note-list-pager-ellipsis-width: 20px; + --note-list-pager-justify-content: flex-end; + + --note-list-pager-current-page-button-background-color: var(--button-group-active-button-background); + --note-list-pager-current-page-button-text-color: var(--button-group-active-button-text-color); +} + +.note-list-pager-container { + display: flex; + flex-direction: column; + width: 100%; + container: note-list-pager / inline-size; +} + +.note-list-pager { + display: flex; + align-items: center; + font-size: .8rem; + align-self: var(--note-list-pager-justify-content); + + .note-list-pager-nav-button { + --icon-button-icon-ratio: .75; + } + + .note-list-pager-page-button-container { + display: flex; + align-items: baseline; + justify-content: space-around; + gap: var(--note-list-pager-page-button-gap); + + &.note-list-pager-ellipsis-present { + /* Prevent the prev/next buttons from shifting when ellipses appear or disappear */ + --_gap-max-width: calc((var(--note-list-pager-page-button-count) + 2) * var(--note-list-pager-page-button-gap)); + + min-width: calc(var(--note-list-pager-page-button-count) * var(--note-list-pager-page-button-width) + + (var(--note-list-pager-ellipsis-width) * 2) + + var(--_gap-max-width)); + } + + .note-list-pager-page-button { + min-width: var(--note-list-pager-page-button-width); + padding-inline: 0; + padding-block: 4px; + + &.note-list-pager-page-button-current { + background: var(--note-list-pager-current-page-button-background-color); + color: var(--note-list-pager-current-page-button-text-color); + font-weight: bold; + opacity: unset; + } + } + + .note-list-pager-ellipsis { + display: inline-block; + width: var(--note-list-pager-ellipsis-width); + text-align: center; + opacity: .5; + } + } + + .note-list-pager-narrow-counter { + display: none; + min-width: 60px; + text-align: center; + white-space: nowrap; + } + + .note-list-pager-total-count { + margin-inline-start: 8px; + opacity: .5; + white-space: nowrap; + } + + @container note-list-pager (max-width: 550px) { + .note-list-pager-page-button-container, + .note-list-pager-total-count { + display: none; + } + + .note-list-pager-narrow-counter { + display: block; + } + } +} + diff --git a/apps/client/src/widgets/collections/Pagination.tsx b/apps/client/src/widgets/collections/Pagination.tsx index 6b74964a64..26d22215cb 100644 --- a/apps/client/src/widgets/collections/Pagination.tsx +++ b/apps/client/src/widgets/collections/Pagination.tsx @@ -4,6 +4,10 @@ import FNote from "../../entities/fnote"; import froca from "../../services/froca"; import { useNoteLabelInt } from "../react/hooks"; import { t } from "../../services/i18n"; +import ActionButton from "../react/ActionButton"; +import Button from "../react/Button"; +import "./Pagination.css"; +import clsx from "clsx"; interface PaginationContext { page: number; @@ -17,46 +21,106 @@ interface PaginationContext { export function Pager({ page, pageSize, setPage, pageCount, totalNotes }: Omit) { if (pageCount < 2) return; - let lastPrinted = false; - let children: ComponentChildren[] = []; - for (let i = 1; i <= pageCount; i++) { - if (pageCount < 20 || i <= 5 || pageCount - i <= 5 || Math.abs(page - i) <= 2) { - lastPrinted = true; - - const startIndex = (i - 1) * pageSize + 1; - const endIndex = Math.min(totalNotes, i * pageSize); - - if (i !== page) { - children.push(( - setPage(i)} - > - {i} - - )) - } else { - // Current page - children.push({i}) - } - - children.push(<>{" "} {" "}); - } else if (lastPrinted) { - children.push(<>{"... "} {" "}); - lastPrinted = false; - } - } - return ( -
- {children} +
+
+ setPage(page - 1)} + /> - ({t("pagination.total_notes", { count: totalNotes })}) + +
+ {page} / {pageCount} +
+ + setPage(page + 1)} + /> + +
+ {t("pagination.total_notes", { count: totalNotes })} +
+
) } +interface PageButtonsProps { + page: number; + setPage: Dispatch>; + pageCount: number; +} + +function PageButtons(props: PageButtonsProps) { + const maxButtonCount = 9; + const maxLeftRightSegmentLength = 2; + + // The left-side segment + const leftLength = Math.min(props.pageCount, maxLeftRightSegmentLength); + const leftStart = 1; + + // The middle segment + const middleMaxLength = maxButtonCount - maxLeftRightSegmentLength * 2; + const middleLength = Math.min(props.pageCount - leftLength, middleMaxLength); + let middleStart = props.page - Math.floor(middleLength / 2); + middleStart = Math.max(middleStart, leftLength + 1); + + // The right-side segment + const rightLength = Math.min(props.pageCount - (middleLength + leftLength), maxLeftRightSegmentLength); + const rightStart = props.pageCount - rightLength + 1; + middleStart = Math.min(middleStart, rightStart - middleLength); + + const totalButtonCount = leftLength + middleLength + rightLength; + const hasLeadingEllipsis = (middleStart - leftLength > 1); + const hasTrailingEllipsis = (rightStart - (middleStart + middleLength - 1) > 1); + + return
+ {[ + ...createSegment(leftStart, leftLength, props.page, props.setPage, false), + ...createSegment(middleStart, middleLength, props.page, props.setPage, hasLeadingEllipsis), + ...createSegment(rightStart, rightLength, props.page, props.setPage, hasTrailingEllipsis), + ]} +
; +} + +function createSegment(start: number, length: number, currentPage: number, setPage: Dispatch>, prependEllipsis: boolean): ComponentChildren[] { + const children: ComponentChildren[] = []; + + if (prependEllipsis) { + children.push(...); + } + + for (let i = 0; i < length; i++) { + const pageNum = start + i; + const isCurrent = (pageNum === currentPage); + children.push(( +
); } +function useLayerData(note: FNote) { + const [ layerName ] = useNoteLabel(note, "map:style"); + // Memo is needed because it would generate unnecessary reloads due to layer change. + const layerData = useMemo(() => { + // Custom layers. + if (layerName?.startsWith("http")) { + return { + name: "Custom", + type: "raster", + url: layerName, + attribution: "" + } satisfies MapLayer; + } + + // Built-in layers. + const layerData = MAP_LAYERS[layerName ?? ""] ?? MAP_LAYERS[DEFAULT_MAP_LAYER_NAME]; + return layerData; + }, [ layerName ]); + + return layerData; +} + function ToggleReadOnlyButton({ note }: { note: FNote }) { const [ isReadOnly, setReadOnly ] = useNoteLabelBoolean(note, "readOnly"); @@ -179,22 +202,26 @@ function ToggleReadOnlyButton({ note }: { note: FNote }) { />; } -function NoteWrapper({ note, isReadOnly }: { note: FNote, isReadOnly: boolean }) { +function NoteWrapper({ note, isReadOnly, hideLabels }: { + note: FNote, + isReadOnly: boolean, + hideLabels: boolean +}) { const mime = useNoteProperty(note, "mime"); const [ location ] = useNoteLabel(note, LOCATION_ATTRIBUTE); if (mime === "application/gpx+xml") { - return ; + return ; } if (location) { const latLng = location?.split(",", 2).map((el) => parseFloat(el)) as [ number, number ] | undefined; if (!latLng) return; - return ; + return ; } } -function NoteMarker({ note, editable, latLng }: { note: FNote, editable: boolean, latLng: [number, number] }) { +function NoteMarker({ note, editable, latLng, hideLabels }: { note: FNote, editable: boolean, latLng: [number, number], hideLabels: boolean }) { // React to changes const [ color ] = useNoteLabel(note, "color"); const [ iconClass ] = useNoteLabel(note, "iconClass"); @@ -202,8 +229,9 @@ function NoteMarker({ note, editable, latLng }: { note: FNote, editable: boolean const title = useNoteProperty(note, "title"); const icon = useMemo(() => { - return buildIcon(note.getIcon(), note.getColorClass() ?? undefined, title, note.noteId, archived); - }, [ iconClass, color, title, note.noteId, archived]); + const titleOrNone = hideLabels ? undefined : title; + return buildIcon(note.getIcon(), note.getColorClass() ?? undefined, titleOrNone, note.noteId, archived); + }, [ iconClass, color, title, note.noteId, archived, hideLabels ]); const onClick = useCallback(() => { appContext.triggerCommand("openInPopup", { noteIdOrPath: note.noteId }); @@ -235,7 +263,7 @@ function NoteMarker({ note, editable, latLng }: { note: FNote, editable: boolean />; } -function NoteGpxTrack({ note }: { note: FNote }) { +function NoteGpxTrack({ note, hideLabels }: { note: FNote, hideLabels?: boolean }) { const [ xmlString, setXmlString ] = useState(); const blob = useNoteBlob(note); @@ -256,7 +284,7 @@ function NoteGpxTrack({ note }: { note: FNote }) { const options = useMemo(() => ({ markers: { - startIcon: buildIcon(note.getIcon(), note.getColorClass(), note.title), + startIcon: buildIcon(note.getIcon(), note.getColorClass(), hideLabels ? undefined : note.title), endIcon: buildIcon("bxs-flag-checkered"), wptIcons: { "": buildIcon("bx bx-pin") @@ -265,7 +293,7 @@ function NoteGpxTrack({ note }: { note: FNote }) { polyline_options: { color: note.getLabelValue("color") ?? "blue" } - }), [ color, iconClass ]); + }), [ color, iconClass, hideLabels ]); return xmlString && ; } diff --git a/apps/client/src/widgets/collections/geomap/map.tsx b/apps/client/src/widgets/collections/geomap/map.tsx index 035f863cc8..19a4586c83 100644 --- a/apps/client/src/widgets/collections/geomap/map.tsx +++ b/apps/client/src/widgets/collections/geomap/map.tsx @@ -1,7 +1,7 @@ import { useEffect, useImperativeHandle, useRef, useState } from "preact/hooks"; import L, { control, LatLng, Layer, LeafletMouseEvent } from "leaflet"; import "leaflet/dist/leaflet.css"; -import { MAP_LAYERS } from "./map_layer"; +import { MAP_LAYERS, type MapLayer } from "./map_layer"; import { ComponentChildren, createContext, RefObject } from "preact"; import { useElementSize, useSyncedRef } from "../../react/hooks"; @@ -12,7 +12,7 @@ interface MapProps { containerRef?: RefObject; coordinates: LatLng | [number, number]; zoom: number; - layerName: string; + layerData: MapLayer; viewportChanged: (coordinates: LatLng, zoom: number) => void; children: ComponentChildren; onClick?: (e: LeafletMouseEvent) => void; @@ -21,7 +21,7 @@ interface MapProps { scale: boolean; } -export default function Map({ coordinates, zoom, layerName, viewportChanged, children, onClick, onContextMenu, scale, apiRef, containerRef: _containerRef, onZoom }: MapProps) { +export default function Map({ coordinates, zoom, layerData, viewportChanged, children, onClick, onContextMenu, scale, apiRef, containerRef: _containerRef, onZoom }: MapProps) { const mapRef = useRef(null); const containerRef = useSyncedRef(_containerRef); @@ -49,8 +49,6 @@ export default function Map({ coordinates, zoom, layerName, viewportChanged, chi const [ layer, setLayer ] = useState(); useEffect(() => { async function load() { - const layerData = MAP_LAYERS[layerName]; - if (layerData.type === "vector") { const style = (typeof layerData.style === "string" ? layerData.style : await layerData.style()); await import("@maplibre/maplibre-gl-leaflet"); @@ -68,7 +66,7 @@ export default function Map({ coordinates, zoom, layerName, viewportChanged, chi } load(); - }, [ layerName ]); + }, [ layerData ]); // Attach layer to the map. useEffect(() => { @@ -139,7 +137,7 @@ export default function Map({ coordinates, zoom, layerName, viewportChanged, chi return (
{children} diff --git a/apps/client/src/widgets/collections/geomap/map_layer.ts b/apps/client/src/widgets/collections/geomap/map_layer.ts index 7b12a10761..bb5f6174e6 100644 --- a/apps/client/src/widgets/collections/geomap/map_layer.ts +++ b/apps/client/src/widgets/collections/geomap/map_layer.ts @@ -1,20 +1,17 @@ -export interface MapLayer { - name: string; - isDarkTheme?: boolean; -} - -interface VectorLayer extends MapLayer { +export type MapLayer = ({ type: "vector"; style: string | (() => Promise<{}>) -} - -interface RasterLayer extends MapLayer { +} | { type: "raster"; url: string; attribution: string; -} +}) & { + // Common properties + name: string; + isDarkTheme?: boolean; +}; -export const MAP_LAYERS: Record = { +export const MAP_LAYERS: Record = { "openstreetmap": { name: "OpenStreetMap", type: "raster", diff --git a/apps/client/src/widgets/collections/legacy/ListOrGridView.css b/apps/client/src/widgets/collections/legacy/ListOrGridView.css index 1bfa389e5c..222682cc9f 100644 --- a/apps/client/src/widgets/collections/legacy/ListOrGridView.css +++ b/apps/client/src/widgets/collections/legacy/ListOrGridView.css @@ -1,5 +1,5 @@ .note-list { - overflow: hidden; + overflow: visible; position: relative; height: 100%; } @@ -100,23 +100,206 @@ overflow: auto; } -.note-expander { - font-size: x-large; - position: relative; - top: 3px; - cursor: pointer; +/* #region List view */ + +@keyframes note-preview-show { + from { + opacity: 0; + } to { + opacity: 1; + } } -.note-list-pager { - text-align: center; +.nested-note-list { + --card-nested-section-indent: 25px; + + &.search-results { + --card-nested-section-indent: 32px; + } } -.note-list.list-view .note-path { - margin-left: 0.5em; - vertical-align: middle; - opacity: 0.5; +/* List item */ +.nested-note-list-item { + h5 { + display: flex; + align-items: center; + font-size: 1em; + font-weight: normal; + margin: 0; + } + + .note-expander { + margin-inline-end: 4px; + font-size: x-large; + cursor: pointer; + } + + .tn-icon { + margin-inline-end: 8px; + color: var(--note-list-view-icon-color); + font-size: 1.2em; + } + + .note-book-title { + --link-hover-background: transparent; + --link-hover-color: currentColor; + color: inherit; + font-weight: normal; + } + + .note-path { + margin-left: 0.5em; + vertical-align: middle; + opacity: 0.5; + } + + .note-list-attributes { + flex-grow: 1; + margin-inline-start: 1em; + text-align: right; + font-size: .75em; + opacity: .75; + } + + .nested-note-list-item-menu { + margin-inline-start: 8px; + flex-shrink: 0; + } + + &.archived { + span.tn-icon + span, + .tn-icon { + opacity: .6; + } + } + + &.use-note-color { + span.tn-icon + span, + .nested-note-list:not(.search-results) & .tn-icon, + .rendered-note-attributes { + color: var(--custom-color); + } + } } +.nested-note-list:not(.search-results) h5 { + span.tn-icon + span, + .note-list-attributes { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } +} + +/* List item (search results view) */ +.nested-note-list.search-results .nested-note-list-item { + span.tn-icon + span > span { + display: flex; + flex-direction: column-reverse; + align-items: flex-start; + } + + small { + line-height: .85em; + } + + .note-path { + margin-left: 0; + font-size: .85em; + line-height: .85em; + font-weight: 500; + letter-spacing: .5pt; + } + + .tn-icon { + display: flex; + flex-shrink: 0; + justify-content: center; + align-items: center; + width: 1.75em; + height: 1.75em; + margin-inline-end: 12px; + border-radius: 50%; + background: var(--note-icon-custom-background-color, var(--note-list-view-large-icon-background)); + font-size: 1.2em; + color: var(--note-icon-custom-color, var(--note-list-view-large-icon-color)); + } + + h5 .ck-find-result { + background: var(--note-list-view-search-result-highlight-background); + color: var(--note-list-view-search-result-highlight-color); + font-weight: 600; + text-decoration: underline; + } +} + +/* Note content preview */ +.nested-note-list .note-book-content { + display: none; + outline: 1px solid var(--note-list-view-content-background); + border-radius: 8px; + background-color: var(--note-list-view-content-background); + overflow: hidden; + user-select: text; + font-size: .85rem; + animation: note-preview-show .25s ease-out; + will-change: opacity; + + &.note-book-content-ready { + display: block; + } + + > .rendered-content > *:last-child { + margin-bottom: 0; + } + + &.type-text { + padding: 8px 24px; + + .ck-content > *:last-child { + margin-bottom: 0; + } + } + + &.type-protectedSession { + padding: 20px; + } + + &.type-image { + padding: 0; + } + + &.type-pdf { + iframe { + height: 50vh; + } + + .file-footer { + padding: 8px; + } + } + + &.type-webView { + display: flex; + flex-direction: column; + justify-content: center; + min-height: 50vh; + } + + .ck-find-result { + outline: 2px solid var(--note-list-view-content-search-result-highlight-background); + border-radius: 4px; + background: var(--note-list-view-content-search-result-highlight-background); + color: var(--note-list-view-content-search-result-highlight-color); + } +} + +.note-content-preview:has(.note-book-content:empty) { + display: none; +} + +/* #endregion */ + /* #region Grid view */ .note-list.grid-view .note-list-container { display: flex; @@ -128,6 +311,10 @@ border: 1px solid transparent; } +body.mobile .note-list.grid-view .note-book-card { + flex-basis: 150px; +} + .note-list.grid-view .note-book-card { max-height: 300px; } diff --git a/apps/client/src/widgets/collections/legacy/ListOrGridView.tsx b/apps/client/src/widgets/collections/legacy/ListOrGridView.tsx index 61c7193a6e..cdde8a6087 100644 --- a/apps/client/src/widgets/collections/legacy/ListOrGridView.tsx +++ b/apps/client/src/widgets/collections/legacy/ListOrGridView.tsx @@ -1,4 +1,5 @@ import "./ListOrGridView.css"; +import { Card, CardSection } from "../../react/Card"; import { useEffect, useRef, useState } from "preact/hooks"; @@ -14,6 +15,11 @@ import NoteLink from "../../react/NoteLink"; import { ViewModeProps } from "../interface"; import { Pager, usePagination } from "../Pagination"; import { filterChildNotes, useFilteredNoteIds } from "./utils"; +import { JSX } from "preact/jsx-runtime"; +import { clsx } from "clsx"; +import ActionButton from "../../react/ActionButton"; +import linkContextMenuService from "../../../menus/link_context_menu"; +import { TargetedMouseEvent } from "preact"; export function ListView({ note, noteIds: unfilteredNoteIds, highlightedTokens }: ViewModeProps<{}>) { const expandDepth = useExpansionDepth(note); @@ -33,7 +39,7 @@ export function ListView({ note, noteIds: unfilteredNoteIds, highlightedTokens } { noteIds.length > 0 &&
{!hasCollectionProperties && } - +
} @@ -93,27 +99,52 @@ function ListNoteCard({ note, parentNote, highlightedTokens, currentLevel, expan // Reset expand state if switching to another note, or if user manually toggled expansion state. useEffect(() => setExpanded(currentLevel <= expandDepth), [ note, currentLevel, expandDepth ]); + let subSections: JSX.Element | undefined = undefined; + if (isExpanded) { + subSections = <> + + + + + + + } + return ( -
-
- setExpanded(!isExpanded)} - /> - +
+ setExpanded(!isExpanded)}/> - + + openNoteMenu(notePath, e)} + />
- - {isExpanded && <> - - - } -
+ ); } @@ -165,6 +196,9 @@ export function NoteContent({ note, trim, noChildrenList, highlightedTokens, inc const contentRef = useRef(null); const highlightSearch = useImperativeSearchHighlighlighting(highlightedTokens); + const [ready, setReady] = useState(false); + const [noteType, setNoteType] = useState("none"); + useEffect(() => { content_renderer.getRenderedContent(note, { trim, @@ -179,17 +213,19 @@ export function NoteContent({ note, trim, noChildrenList, highlightedTokens, inc } else { contentRef.current.replaceChildren(); } - contentRef.current.classList.add(`type-${type}`); highlightSearch(contentRef.current); + setNoteType(type); + setReady(true); }) .catch(e => { console.warn(`Caught error while rendering note '${note.noteId}' of type '${note.type}'`); console.error(e); contentRef.current?.replaceChildren(t("collections.rendering_error")); + setReady(true); }); }, [ note, highlightedTokens ]); - return
; + return
; } function NoteChildren({ note, parentNote, highlightedTokens, currentLevel, expandDepth, includeArchived }: { @@ -238,3 +274,8 @@ function useExpansionDepth(note: FNote) { return parseInt(expandDepth, 10); } + +function openNoteMenu(notePath, e: TargetedMouseEvent) { + linkContextMenuService.openContextMenu(notePath, e); + e.stopPropagation() +} diff --git a/apps/client/src/widgets/containers/root_container.ts b/apps/client/src/widgets/containers/root_container.ts index 03df4a8ec6..ea79893d19 100644 --- a/apps/client/src/widgets/containers/root_container.ts +++ b/apps/client/src/widgets/containers/root_container.ts @@ -1,11 +1,12 @@ -import { EventData } from "../../components/app_context.js"; import { LOCALES } from "@triliumnext/commons"; -import { readCssVar } from "../../utils/css-var.js"; -import FlexContainer from "./flex_container.js"; -import options from "../../services/options.js"; -import type BasicWidget from "../basic_widget.js"; -import utils from "../../services/utils.js"; + +import { EventData } from "../../components/app_context.js"; import { getEnabledExperimentalFeatureIds } from "../../services/experimental_features.js"; +import options from "../../services/options.js"; +import utils, { isMobile } from "../../services/utils.js"; +import { readCssVar } from "../../utils/css-var.js"; +import type BasicWidget from "../basic_widget.js"; +import FlexContainer from "./flex_container.js"; /** * The root container is the top-most widget/container, from which the entire layout derives. @@ -17,14 +18,12 @@ import { getEnabledExperimentalFeatureIds } from "../../services/experimental_fe * - `#root-container.vertical-layout`, if the current layout is horizontal. */ export default class RootContainer extends FlexContainer { - private originalViewportHeight: number; constructor(isHorizontalLayout: boolean) { super(isHorizontalLayout ? "column" : "row"); this.id("root-widget"); this.css("height", "100dvh"); - this.originalViewportHeight = getViewportHeight(); } render(): JQuery { @@ -39,6 +38,7 @@ export default class RootContainer extends FlexContainer { this.#setThemeCapabilities(); this.#setLocaleAndDirection(options.get("locale")); this.#setExperimentalFeatures(); + this.#initPWATopbarColor(); return super.render(); } @@ -64,8 +64,12 @@ export default class RootContainer extends FlexContainer { } #onMobileResize() { - const currentViewportHeight = getViewportHeight(); - const isKeyboardOpened = (currentViewportHeight < this.originalViewportHeight); + const viewportHeight = window.visualViewport?.height ?? window.innerHeight; + const windowHeight = window.innerHeight; + + // If viewport is significantly smaller, keyboard is likely open + const isKeyboardOpened = windowHeight - viewportHeight > 150; + this.$widget.toggleClass("virtual-keyboard-opened", isKeyboardOpened); } @@ -88,7 +92,7 @@ export default class RootContainer extends FlexContainer { } #setBackdropEffects() { - const enabled = options.is("backdropEffectsEnabled"); + const enabled = options.is("backdropEffectsEnabled") && !isMobile(); document.body.classList.toggle("backdrop-effects-disabled", !enabled); } @@ -96,7 +100,7 @@ export default class RootContainer extends FlexContainer { // Supports background effects const useBgfx = readCssVar(document.documentElement, "allow-background-effects") - .asBoolean(false); + .asBoolean(false); document.body.classList.toggle("theme-supports-background-effects", useBgfx); } @@ -112,8 +116,23 @@ export default class RootContainer extends FlexContainer { document.body.lang = locale; document.body.dir = correspondingLocale?.rtl ? "rtl" : "ltr"; } + + #initPWATopbarColor() { + if (!utils.isPWA()) return; + const tracker = $("#background-color-tracker"); + + if (tracker.length) { + const applyThemeColor = () => { + let meta = $("meta[name='theme-color']"); + if (!meta.length) { + meta = $(``).appendTo($("head")); + } + meta.attr("content", tracker.css("color")); + }; + + tracker.on("transitionend", applyThemeColor); + applyThemeColor(); + } + } } -function getViewportHeight() { - return window.visualViewport?.height ?? window.innerHeight; -} diff --git a/apps/client/src/widgets/containers/scrolling_container.css b/apps/client/src/widgets/containers/scrolling_container.css index 2a2adb1475..a3fae557a3 100644 --- a/apps/client/src/widgets/containers/scrolling_container.css +++ b/apps/client/src/widgets/containers/scrolling_container.css @@ -1,14 +1,26 @@ .scrolling-container { + --content-margin-inline: 24px; + overflow: auto; scroll-behavior: smooth; position: relative; - > .inline-title, - > .note-detail > .note-detail-editable-text, + > .note-detail > .note-detail-editable-text > .note-detail-editable-text-editor, > .note-list-widget:not(.full-height) .note-list-wrapper { - padding-inline: 24px; + margin-inline: var(--content-margin-inline); } + > .inline-title { + padding-inline: var(--content-margin-inline); + } + + > .note-detail > .note-detail-editable-text > .note-detail-editable-text-editor { + overflow: unset; + } +} + +body.mobile .scrolling-container { + --content-margin-inline: 8px; } .note-split.type-code:not(.mime-text-x-sqlite) { diff --git a/apps/client/src/widgets/dialogs/PopupEditor.css b/apps/client/src/widgets/dialogs/PopupEditor.css index 197ed94065..84f4c93197 100644 --- a/apps/client/src/widgets/dialogs/PopupEditor.css +++ b/apps/client/src/widgets/dialogs/PopupEditor.css @@ -32,6 +32,12 @@ body.mobile .modal.popup-editor-dialog .modal-dialog { display: flex; align-items: center; margin-block: 0; + + .note-icon-widget { + display: flex; + align-items: center; + margin-inline-start: 0; + } } .modal.popup-editor-dialog .modal-header .note-title-widget { @@ -91,8 +97,9 @@ body.mobile .modal.popup-editor-dialog .modal-dialog { height: 100%; } -.modal.popup-editor-dialog .note-detail-editable-text { - padding: 0 1em; +.modal.popup-editor-dialog .note-detail-editable-text-editor { + margin: 0 28px; + overflow: visible; /* Allow selection rectangle to go outside of the editor area */ } .modal.popup-editor-dialog .note-detail-file { diff --git a/apps/client/src/widgets/dialogs/PopupEditor.tsx b/apps/client/src/widgets/dialogs/PopupEditor.tsx index e8e73ae785..07363b2e91 100644 --- a/apps/client/src/widgets/dialogs/PopupEditor.tsx +++ b/apps/client/src/widgets/dialogs/PopupEditor.tsx @@ -5,13 +5,15 @@ import { useContext, useEffect, useMemo, useRef, useState } from "preact/hooks"; import appContext from "../../components/app_context"; import NoteContext from "../../components/note_context"; +import { isExperimentalFeatureEnabled } from "../../services/experimental_features"; import froca from "../../services/froca"; import { t } from "../../services/i18n"; import tree from "../../services/tree"; import utils from "../../services/utils"; import NoteList from "../collections/NoteList"; import FloatingButtons from "../FloatingButtons"; -import { DESKTOP_FLOATING_BUTTONS, MOBILE_FLOATING_BUTTONS, POPUP_HIDDEN_FLOATING_BUTTONS } from "../FloatingButtonsDefinitions"; +import { DESKTOP_FLOATING_BUTTONS, POPUP_HIDDEN_FLOATING_BUTTONS } from "../FloatingButtonsDefinitions"; +import NoteBadges from "../layout/NoteBadges"; import NoteIcon from "../note_icon"; import NoteTitleWidget from "../note_title"; import NoteDetail from "../NoteDetail"; @@ -23,8 +25,6 @@ import ReadOnlyNoteInfoBar from "../ReadOnlyNoteInfoBar"; import StandaloneRibbonAdapter from "../ribbon/components/StandaloneRibbonAdapter"; import FormattingToolbar from "../ribbon/FormattingToolbar"; import MobileEditorToolbar from "../type_widgets/text/mobile_editor_toolbar"; -import NoteBadges from "../layout/NoteBadges"; -import { isExperimentalFeatureEnabled } from "../../services/experimental_features"; const isNewLayout = isExperimentalFeatureEnabled("new-layout"); @@ -34,7 +34,7 @@ export default function PopupEditor() { const [ noteContext, setNoteContext ] = useState(new NoteContext("_popup-editor")); const isMobile = utils.isMobile(); const items = useMemo(() => { - const baseItems = isMobile ? MOBILE_FLOATING_BUTTONS : DESKTOP_FLOATING_BUTTONS; + const baseItems = isMobile ? [] : DESKTOP_FLOATING_BUTTONS; return baseItems.filter(item => !POPUP_HIDDEN_FLOATING_BUTTONS.includes(item)); }, [ isMobile ]); @@ -67,10 +67,7 @@ export default function PopupEditor() { - - {isNewLayout && } - } + title={} customTitleBarButtons={[{ iconClassName: "bx-expand-alt", title: t("popup-editor.maximize"), @@ -123,6 +120,7 @@ export function TitleRow() {
+ {isNewLayout && }
); } diff --git a/apps/client/src/widgets/dialogs/bulk_actions.tsx b/apps/client/src/widgets/dialogs/bulk_actions.tsx index 05033255c4..cbb04a404a 100644 --- a/apps/client/src/widgets/dialogs/bulk_actions.tsx +++ b/apps/client/src/widgets/dialogs/bulk_actions.tsx @@ -57,7 +57,7 @@ export default function BulkActionsDialog() { className="bulk-actions-dialog" size="xl" title={t("bulk_actions.bulk_actions")} - footer={
+ } + mobile={ + + {childNotes?.map(childNote => )} + + } + /> + ); } function SingleBookmark({ note }: { note: FNote }) { const [ bookmarkFolder ] = useNoteLabelBoolean(note, "bookmarkFolder"); - return bookmarkFolder - ? - : note.noteId} /> + return + : note.noteId} /> + } + mobile={} + />; +} + +function MobileBookmarkItem({ noteId, bookmarkFolder }: { noteId: string, bookmarkFolder: boolean }) { + const note = useNote(noteId); + const noteIcon = useNoteIcon(note); + if (!note) return null; + + return ( + !bookmarkFolder + ? launchCustomNoteLauncher(e, { launcherNote: note, getTargetNoteId: () => note.noteId })}>{note.title} + : + ); +} + +function MobileBookmarkFolder({ note }: { note: FNote }) { + const childNotes = useChildNotes(note.noteId); + + return ( + + {childNotes.map(childNote => ( + launchCustomNoteLauncher(e, { launcherNote: childNote, getTargetNoteId: () => childNote.noteId })} + > + {childNote.title} + + ))} + + ); } function BookmarkFolder({ note }: { note: FNote }) { @@ -55,5 +107,5 @@ function BookmarkFolder({ note }: { note: FNote }) {
- ) + ); } diff --git a/apps/client/src/widgets/launch_bar/GenericButtons.tsx b/apps/client/src/widgets/launch_bar/GenericButtons.tsx index 70fe0fccef..59c158dec1 100644 --- a/apps/client/src/widgets/launch_bar/GenericButtons.tsx +++ b/apps/client/src/widgets/launch_bar/GenericButtons.tsx @@ -7,32 +7,18 @@ import { isCtrlKey } from "../../services/utils"; import { useGlobalShortcut, useNoteLabel } from "../react/hooks"; import { LaunchBarActionButton, useLauncherIconAndTitle } from "./launch_bar_widgets"; -export function CustomNoteLauncher({ launcherNote, getTargetNoteId, getHoistedNoteId }: { +export function CustomNoteLauncher(props: { launcherNote: FNote; getTargetNoteId: (launcherNote: FNote) => string | null | Promise; getHoistedNoteId?: (launcherNote: FNote) => string | null; keyboardShortcut?: string; }) { + const { launcherNote, getTargetNoteId } = props; const { icon, title } = useLauncherIconAndTitle(launcherNote); const launch = useCallback(async (evt: MouseEvent | KeyboardEvent) => { - if (evt.which === 3) { - return; - } - - const targetNoteId = await getTargetNoteId(launcherNote); - if (!targetNoteId) return; - - const hoistedNoteIdWithDefault = getHoistedNoteId?.(launcherNote) || appContext.tabManager.getActiveContext()?.hoistedNoteId; - const ctrlKey = isCtrlKey(evt); - - if ((evt.which === 1 && ctrlKey) || evt.which === 2) { - const activate = !!evt.shiftKey; - await appContext.tabManager.openInNewTab(targetNoteId, hoistedNoteIdWithDefault, activate); - } else { - await appContext.tabManager.openInSameTab(targetNoteId, hoistedNoteIdWithDefault); - } - }, [ launcherNote, getTargetNoteId, getHoistedNoteId ]); + await launchCustomNoteLauncher(evt, props); + }, [ props ]); // Keyboard shortcut. const [ shortcut ] = useNoteLabel(launcherNote, "keyboardShortcut"); @@ -54,3 +40,24 @@ export function CustomNoteLauncher({ launcherNote, getTargetNoteId, getHoistedNo /> ); } + +export async function launchCustomNoteLauncher(evt: MouseEvent | KeyboardEvent, { launcherNote, getTargetNoteId, getHoistedNoteId }: { + launcherNote: FNote; + getTargetNoteId: (launcherNote: FNote) => string | null | Promise; + getHoistedNoteId?: (launcherNote: FNote) => string | null; +}) { + if (evt.which === 3) return; + + const targetNoteId = await getTargetNoteId(launcherNote); + if (!targetNoteId) return; + + const hoistedNoteIdWithDefault = getHoistedNoteId?.(launcherNote) || appContext.tabManager.getActiveContext()?.hoistedNoteId; + const ctrlKey = isCtrlKey(evt); + + if ((evt.which === 1 && ctrlKey) || evt.which === 2) { + const activate = !!evt.shiftKey; + await appContext.tabManager.openInNewTab(targetNoteId, hoistedNoteIdWithDefault, activate); + } else { + await appContext.tabManager.openInSameTab(targetNoteId, hoistedNoteIdWithDefault); + } +} diff --git a/apps/client/src/widgets/launch_bar/SyncStatus.tsx b/apps/client/src/widgets/launch_bar/SyncStatus.tsx index f5919f912b..651b89c075 100644 --- a/apps/client/src/widgets/launch_bar/SyncStatus.tsx +++ b/apps/client/src/widgets/launch_bar/SyncStatus.tsx @@ -1,12 +1,14 @@ -import { useEffect, useRef, useState } from "preact/hooks"; import "./SyncStatus.css"; -import { t } from "../../services/i18n"; -import clsx from "clsx"; -import { escapeQuotes } from "../../services/utils"; -import { useStaticTooltip, useTriliumOption } from "../react/hooks"; -import sync from "../../services/sync"; -import ws, { subscribeToMessages, unsubscribeToMessage } from "../../services/ws"; + import { WebSocketMessage } from "@triliumnext/commons"; +import clsx from "clsx"; +import { useEffect, useRef, useState } from "preact/hooks"; + +import { t } from "../../services/i18n"; +import sync from "../../services/sync"; +import { escapeQuotes } from "../../services/utils"; +import ws, { subscribeToMessages, unsubscribeToMessage } from "../../services/ws"; +import { useStaticTooltip, useTriliumOption } from "../react/hooks"; type SyncState = "unknown" | "in-progress" | "connected-with-changes" | "connected-no-changes" @@ -53,29 +55,29 @@ export default function SyncStatus() { const spanRef = useRef(null); const [ syncServerHost ] = useTriliumOption("syncServerHost"); useStaticTooltip(spanRef, { - html: true - // TODO: Placement + html: true, + title: escapeQuotes(title) }); return (syncServerHost &&
{ if (syncState === "in-progress") return; sync.syncNow(); }} > {hasChanges && ( - + )}
- ) + ); } function useSyncStatus() { diff --git a/apps/client/src/widgets/launch_bar/launch_bar_widgets.tsx b/apps/client/src/widgets/launch_bar/launch_bar_widgets.tsx index bb4a053c89..288565cf7b 100644 --- a/apps/client/src/widgets/launch_bar/launch_bar_widgets.tsx +++ b/apps/client/src/widgets/launch_bar/launch_bar_widgets.tsx @@ -3,11 +3,14 @@ import { createContext } from "preact"; import { useContext } from "preact/hooks"; import FNote from "../../entities/fnote"; +import utils from "../../services/utils"; import ActionButton, { ActionButtonProps } from "../react/ActionButton"; import Dropdown, { DropdownProps } from "../react/Dropdown"; import { useNoteLabel, useNoteProperty } from "../react/hooks"; import Icon from "../react/Icon"; +const cachedIsMobile = utils.isMobile(); + export const LaunchBarContext = createContext<{ isHorizontalLayout: boolean; }>({ @@ -26,7 +29,7 @@ export function LaunchBarActionButton({ className, ...props }: Omit ); @@ -34,6 +37,7 @@ export function LaunchBarActionButton({ className, ...props }: Omit & { icon: string }) { const { isHorizontalLayout } = useContext(LaunchBarContext); + const titlePosition = getTitlePosition(isHorizontalLayout); return ( } - titlePosition={isHorizontalLayout ? "bottom" : "right"} + titlePosition={titlePosition} titleOptions={{ animation: false }} dropdownOptions={{ ...dropdownOptions, popperConfig: { - placement: isHorizontalLayout ? "bottom" : "right" + placement: titlePosition } }} + mobileBackdrop {...props} >{children} ); @@ -66,3 +71,10 @@ export function useLauncherIconAndTitle(note: FNote) { title: title ?? "" }; } + +function getTitlePosition(isHorizontalLayout: boolean) { + if (cachedIsMobile) { + return "top"; + } + return isHorizontalLayout ? "bottom" : "right"; +} diff --git a/apps/client/src/widgets/layout/ActiveContentBadges.tsx b/apps/client/src/widgets/layout/ActiveContentBadges.tsx new file mode 100644 index 0000000000..8d0cf20c75 --- /dev/null +++ b/apps/client/src/widgets/layout/ActiveContentBadges.tsx @@ -0,0 +1,284 @@ +import { BUILTIN_ATTRIBUTES } from "@triliumnext/commons"; +import clsx from "clsx"; +import { useEffect, useState } from "preact/hooks"; + +import FNote from "../../entities/fnote"; +import attributes from "../../services/attributes"; +import { t } from "../../services/i18n"; +import { openInAppHelpFromUrl } from "../../services/utils"; +import { BadgeWithDropdown } from "../react/Badge"; +import { FormDropdownDivider, FormListItem } from "../react/FormList"; +import FormToggle from "../react/FormToggle"; +import { useNoteContext, useNoteProperty, useTriliumEvent } from "../react/hooks"; +import { BookProperty, ViewProperty } from "../react/NotePropertyMenu"; + +const NON_DANGEROUS_ACTIVE_CONTENT = [ "appCss", "appTheme" ]; +const DANGEROUS_ATTRIBUTES = BUILTIN_ATTRIBUTES.filter(a => a.isDangerous || NON_DANGEROUS_ACTIVE_CONTENT.includes(a.name)); +const activeContentLabels = [ "iconPack", "widget", "appCss", "appTheme" ] as const; + +interface ActiveContentInfo { + type: "iconPack" | "backendScript" | "frontendScript" | "widget" | "appCss" | "renderNote" | "webView" | "appTheme"; + isEnabled: boolean; + canToggleEnabled: boolean; +} + +const executeOption: BookProperty = { + type: "button", + icon: "bx bx-play", + label: t("active_content_badges.menu_execute_now"), + onClick: context => context.triggerCommand("runActiveNote") +}; + +const typeMappings: Record = { + iconPack: { + title: t("active_content_badges.type_icon_pack"), + icon: "bx bx-package", + helpPage: "g1mlRoU8CsqC", + }, + backendScript: { + title: t("active_content_badges.type_backend_script"), + icon: "bx bx-server", + helpPage: "SPirpZypehBG", + apiDocsPage: "MEtfsqa5VwNi", + isExecutable: true, + additionalOptions: [ + executeOption, + { + type: "combobox", + bindToLabel: "run", + label: t("active_content_badges.menu_run"), + icon: "bx bx-rss", + dropStart: true, + options: [ + { value: null, label: t("active_content_badges.menu_run_disabled") }, + { value: "backendStartup", label: t("active_content_badges.menu_run_backend_startup") }, + { value: "daily", label: t("active_content_badges.menu_run_daily") }, + { value: "hourly", label: t("active_content_badges.menu_run_hourly") } + ] + } + ] + }, + frontendScript: { + title: t("active_content_badges.type_frontend_script"), + icon: "bx bx-window", + helpPage: "yIhgI5H7A2Sm", + apiDocsPage: "Q2z6av6JZVWm", + isExecutable: true, + additionalOptions: [ + executeOption, + { + type: "combobox", + bindToLabel: "run", + label: t("active_content_badges.menu_run"), + icon: "bx bx-rss", + dropStart: true, + options: [ + { value: null, label: t("active_content_badges.menu_run_disabled") }, + { value: "frontendStartup", label: t("active_content_badges.menu_run_frontend_startup") }, + { value: "mobileStartup", label: t("active_content_badges.menu_run_mobile_startup") }, + ] + }, + { type: "separator" }, + { + type: "button", + label: t("active_content_badges.menu_change_to_widget"), + icon: "bx bxs-widget", + onClick: ({ note }) => attributes.setLabel(note.noteId, "widget") + } + ] + }, + widget: { + title: t("active_content_badges.type_widget"), + icon: "bx bxs-widget", + helpPage: "MgibgPcfeuGz", + additionalOptions: [ + { + type: "button", + label: t("active_content_badges.menu_change_to_frontend_script"), + icon: "bx bx-window", + onClick: ({ note }) => { + attributes.removeOwnedLabelByName(note, "widget"); + attributes.removeOwnedLabelByName(note, "disabled:widget"); + } + } + ] + }, + appCss: { + title: t("active_content_badges.type_app_css"), + icon: "bx bxs-file-css", + helpPage: "AlhDUqhENtH7" + }, + renderNote: { + title: t("active_content_badges.type_render_note"), + icon: "bx bx-extension", + helpPage: "HcABDtFCkbFN" + }, + webView: { + title: t("active_content_badges.type_web_view"), + icon: "bx bx-globe", + helpPage: "1vHRoWCEjj0L" + }, + appTheme: { + title :t("active_content_badges.type_app_theme"), + icon: "bx bx-palette", + helpPage: "7NfNr5pZpVKV", + additionalOptions: [ + { + type: "combobox", + bindToLabel: "appThemeBase", + label: t("active_content_badges.menu_theme_base"), + icon: "bx bx-layer", + dropStart: true, + options: [ + { label: t("theme.auto_theme"), value: null }, + { type: "separator" }, + { label: t("theme.triliumnext"), value: "next" }, + { label: t("theme.triliumnext-light"), value: "next-light" }, + { label: t("theme.triliumnext-dark"), value: "next-dark" } + ] + } + ] + } +}; + +export function ActiveContentBadges() { + const { note } = useNoteContext(); + const info = useActiveContentInfo(note); + + return (note && info && + <> + {info.canToggleEnabled && } + + + ); +} + +function ActiveContentBadge({ info, note }: { note: FNote, info: ActiveContentInfo }) { + const { title, icon, helpPage, apiDocsPage, additionalOptions } = typeMappings[info.type]; + return ( + + {additionalOptions?.length && ( + <> + {additionalOptions?.map((property, i) => ( + + ))} + + + )} + + openInAppHelpFromUrl(helpPage)} + >{t("active_content_badges.menu_docs")} + + {apiDocsPage && openInAppHelpFromUrl(apiDocsPage)} + >{t("code_buttons.trilium_api_docs_button_title")}} + + ); +} + +function ActiveContentToggle({ note, info }: { note: FNote, info: ActiveContentInfo }) { + const { title } = typeMappings[info.type]; + + return info && { + await Promise.all(note.getOwnedAttributes() + .map(attr => ({ name: attributes.getNameWithoutDangerousPrefix(attr.name), type: attr.type })) + .filter(({ name, type }) => DANGEROUS_ATTRIBUTES.some(item => item.name === name && item.type === type)) + .map(({ name, type }) => attributes.toggleDangerousAttribute(note, type, name, willEnable))); + }} + />; +} + +function useActiveContentInfo(note: FNote | null | undefined) { + const [ info, setInfo ] = useState(null); + const noteType = useNoteProperty(note, "type"); + const noteMime = useNoteProperty(note, "mime"); + + function refresh() { + let type: ActiveContentInfo["type"] | null = null; + let isEnabled = false; + let canToggleEnabled = false; + + if (!note) { + setInfo(null); + return; + } + + if (noteType === "render") { + type = "renderNote"; + isEnabled = note.hasRelation("renderNote"); + } else if (noteType === "webView") { + type = "webView"; + isEnabled = note.hasLabel("webViewSrc"); + } else if (noteType === "code" && noteMime === "application/javascript;env=backend") { + type = "backendScript"; + for (const backendLabel of [ "run", "customRequestHandler", "customResourceProvider" ]) { + isEnabled ||= note.hasLabel(backendLabel); + + if (!canToggleEnabled && note.hasLabelOrDisabled(backendLabel)) { + canToggleEnabled = true; + } + } + } else if (noteType === "code" && noteMime === "application/javascript;env=frontend") { + type = "frontendScript"; + isEnabled = note.hasLabel("widget") || note.hasLabel("run"); + canToggleEnabled = note.hasLabelOrDisabled("widget") || note.hasLabelOrDisabled("run"); + } else if (noteType === "code" && note.hasLabelOrDisabled("appTheme")) { + isEnabled = note.hasLabel("appTheme"); + canToggleEnabled = true; + } + + for (const labelToCheck of activeContentLabels) { + if (note.hasLabel(labelToCheck)) { + type = labelToCheck; + isEnabled = true; + canToggleEnabled = true; + break; + } else if (note.hasLabel(`disabled:${labelToCheck}`)) { + type = labelToCheck; + isEnabled = false; + canToggleEnabled = true; + break; + } + } + + if (type) { + setInfo({ type, isEnabled, canToggleEnabled }); + } else { + setInfo(null); + } + } + + // Refresh on note change. + useEffect(refresh, [ note, noteType, noteMime ]); + + useTriliumEvent("entitiesReloaded", ({ loadResults }) => { + if (loadResults.getAttributeRows().some(attr => attributes.isAffecting(attr, note))) { + refresh(); + } + }); + + return info; +} diff --git a/apps/client/src/widgets/layout/Breadcrumb.css b/apps/client/src/widgets/layout/Breadcrumb.css index 18f88ac0c8..c32bc50dac 100644 --- a/apps/client/src/widgets/layout/Breadcrumb.css +++ b/apps/client/src/widgets/layout/Breadcrumb.css @@ -19,6 +19,9 @@ --link-hover-background: var(--icon-button-hover-background); color: var(--custom-color, inherit); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; &:hover { color: var(--custom-color, inherit); diff --git a/apps/client/src/widgets/layout/NoteBadges.css b/apps/client/src/widgets/layout/NoteBadges.css index ec163da6f2..013963adb4 100644 --- a/apps/client/src/widgets/layout/NoteBadges.css +++ b/apps/client/src/widgets/layout/NoteBadges.css @@ -37,6 +37,10 @@ pointer-events: none; } } + &.active-content-badge { --color: var(--badge-active-content-background-color); } + &.active-content-badge.disabled { + opacity: 0.5; + } min-width: 0; @@ -45,6 +49,11 @@ text-overflow: ellipsis; min-width: 0; } + + .switch-button { + --switch-track-height: 8px; + --switch-track-width: 30px; + } } .dropdown-badge { diff --git a/apps/client/src/widgets/layout/NoteBadges.tsx b/apps/client/src/widgets/layout/NoteBadges.tsx index b4fba9e28a..bf484edf73 100644 --- a/apps/client/src/widgets/layout/NoteBadges.tsx +++ b/apps/client/src/widgets/layout/NoteBadges.tsx @@ -10,6 +10,7 @@ import { FormDropdownDivider, FormListItem } from "../react/FormList"; import { useGetContextData, useIsNoteReadOnly, useNoteContext, useNoteLabel, useNoteLabelBoolean } from "../react/hooks"; import { useShareState } from "../ribbon/BasicPropertiesTab"; import { useShareInfo } from "../shared_info"; +import { ActiveContentBadges } from "./ActiveContentBadges"; export default function NoteBadges() { return ( @@ -19,6 +20,7 @@ export default function NoteBadges() { +
); } diff --git a/apps/client/src/widgets/layout/NoteTitleActions.css b/apps/client/src/widgets/layout/NoteTitleActions.css index b1aa37d89c..4ae4c15816 100644 --- a/apps/client/src/widgets/layout/NoteTitleActions.css +++ b/apps/client/src/widgets/layout/NoteTitleActions.css @@ -50,6 +50,9 @@ body.experimental-feature-new-layout { } } + } + + body.desktop .title-actions { > .collapsible, > .note-type-switcher { padding-inline-start: calc(24px - var(--title-actions-padding-start)); @@ -57,3 +60,4 @@ body.experimental-feature-new-layout { } } } + diff --git a/apps/client/src/widgets/layout/NoteTitleActions.tsx b/apps/client/src/widgets/layout/NoteTitleActions.tsx index 6886acc7e6..73ad3e0e89 100644 --- a/apps/client/src/widgets/layout/NoteTitleActions.tsx +++ b/apps/client/src/widgets/layout/NoteTitleActions.tsx @@ -1,25 +1,21 @@ import "./NoteTitleActions.css"; -import clsx from "clsx"; import { useEffect, useState } from "preact/hooks"; import NoteContext from "../../components/note_context"; import FNote from "../../entities/fnote"; import { t } from "../../services/i18n"; -import CollectionProperties from "../note_bars/CollectionProperties"; import { checkFullHeight, getExtendedWidgetType } from "../NoteDetail"; import { PromotedAttributesContent, usePromotedAttributeData } from "../PromotedAttributes"; -import SimpleBadge from "../react/Badge"; import Collapsible, { ExternallyControlledCollapsible } from "../react/Collapsible"; import { useNoteContext, useNoteLabel, useNoteProperty, useTriliumEvent, useTriliumOptionBool } from "../react/hooks"; -import NoteLink, { NewNoteLink } from "../react/NoteLink"; +import { NewNoteLink } from "../react/NoteLink"; import { useEditedNotes } from "../ribbon/EditedNotesTab"; import SearchDefinitionTab from "../ribbon/SearchDefinitionTab"; import NoteTypeSwitcher from "./NoteTypeSwitcher"; export default function NoteTitleActions() { - const { note, ntxId, componentId, noteContext } = useNoteContext(); - const isHiddenNote = note && note.noteId !== "_search" && note.noteId.startsWith("_"); + const { note, ntxId, componentId, noteContext, viewScope } = useNoteContext(); const noteType = useNoteProperty(note, "type"); return ( @@ -27,7 +23,7 @@ export default function NoteTitleActions() { {noteType === "search" && } - + {(!viewScope?.viewMode || viewScope.viewMode === "default") && }
); } @@ -48,7 +44,7 @@ function PromotedAttributes({ note, componentId, noteContext }: { componentId: string, noteContext: NoteContext | undefined }) { - const [ cells, setCells ] = usePromotedAttributeData(note, componentId); + const [ cells, setCells ] = usePromotedAttributeData(note, componentId, noteContext); const [ expanded, setExpanded ] = useState(false); useEffect(() => { diff --git a/apps/client/src/widgets/layout/StatusBar.css b/apps/client/src/widgets/layout/StatusBar.css index c421c3d65e..c8d01c83be 100644 --- a/apps/client/src/widgets/layout/StatusBar.css +++ b/apps/client/src/widgets/layout/StatusBar.css @@ -37,6 +37,10 @@ &:hover { background: var(--input-background-color); } + + .text { + white-space: nowrap; + } } .status-bar-dropdown-button { @@ -58,101 +62,12 @@ .dropdown-note-info { padding: 1em !important; - - ul { - --row-block-margin: .2em; - - list-style-type: none; - padding: 0; - margin: 0; - margin-top: calc(0px - var(--row-block-margin)); - margin-bottom: 12px; - display: table; - - li { - display: table-row; - - > strong { - display: table-cell; - padding: var(--row-block-margin) 0; - opacity: .5; - } - - > span { - display: table-cell; - user-select: text; - padding-left: 2em; - } - } - } } .dropdown-note-paths { .note-paths-widget { padding: 0.5em; } - - .note-path-intro { - color: var(--muted-text-color); - } - - .note-path-list { - margin: 12px 0; - padding: 0; - list-style: none; - - /* Note path card */ - li { - --border-radius: 6px; - - position: relative; - background: var(--card-background-color); - padding: 8px 20px 8px 25px; - - &:first-child { - border-radius: var(--border-radius) var(--border-radius) 0 0; - } - - &:last-child { - border-radius: 0 0 var(--border-radius) var(--border-radius); - } - - & + li { - margin-top: 2px; - } - - /* Current path arrow */ - &.path-current::before { - position: absolute; - display: flex; - justify-content: flex-end; - align-items: center; - content: "\ee8f"; - top: 0; - left: 0; - width: 20px; - bottom: 0; - font-family: "boxicons"; - font-size: .75em; - color: var(--menu-item-icon-color); - } - } - - /* Note path segment */ - a { - margin-inline: 2px; - padding-inline: 2px; - color: currentColor; - font-weight: normal; - text-decoration: none; - - /* The last segment of the note path */ - &.basename { - color: var(--muted-text-color); - } - } - - } } .backlinks-widget > .dropdown-menu { @@ -160,84 +75,6 @@ max-height: 60vh; overflow-y: scroll; - - /* Backlink card */ - li { - --border-radius: 8px; - - max-width: 600px; - padding: 10px 20px; - background: var(--card-background-color); - - & + li { - margin-top: 2px; - } - - &:first-child { - border-radius: var(--border-radius) var(--border-radius) 0 0; - } - - &:last-child { - border-radius: 0 0 var(--border-radius) var(--border-radius); - } - - /* Card header */ - & > span:first-child { - display: block; - - > span { - display: flex; - flex-wrap: wrap; - align-items: center; - - /* Note path */ - > small { - flex: 100%; - order: -1; - font-size: .65rem; - - .note-path { - padding: 0; - } - } - - /* Note icon */ - > .tn-icon { - color: var(--menu-item-icon-color); - } - - /* Note title */ - > a { - margin-inline-start: 4px; - color: currentColor; - font-weight: 500; - } - } - } - - /* Card content - excerpt */ - & > span:nth-child(2) > div { - all: unset; /* TODO: Remove after disposing the old style from FloatingButtons.css */ - display: block; - - margin: 8px 0; - border-radius: 4px; - background: var(--quick-search-result-content-background); - padding: 8px; - font-size: .75rem; - - a { - background: transparent; - color: var(--quick-search-result-highlight-color); - text-decoration: underline; - } - - p { - margin: 0; - } - } - - } } } @@ -284,16 +121,50 @@ } - div.similar-notes-widget div.similar-notes-wrapper { - max-height: unset; - } - button.select-button:not(:focus-visible) { outline: none; } } +body.experimental-feature-new-layout .note-info-content { + ul { + --row-block-margin: .2em; + + list-style-type: none; + padding: 0; + margin: 0; + margin-top: calc(0px - var(--row-block-margin)); + margin-bottom: 12px; + display: table; + + li { + display: table-row; + + > strong { + display: table-cell; + padding: var(--row-block-margin) 0; + opacity: .5; + } + + > span { + display: table-cell; + user-select: text; + padding-left: 2em; + } + } + } +} + +body.experimental-feature-new-layout div.similar-notes-widget div.similar-notes-wrapper { + max-height: unset; +} + +body.experimental-feature-new-layout.mobile div.similar-notes-widget div.similar-notes-wrapper { + max-height: unset; + padding: 0; +} + .bottom-panel { margin: 0 !important; padding: 0; diff --git a/apps/client/src/widgets/layout/StatusBar.tsx b/apps/client/src/widgets/layout/StatusBar.tsx index 903aeca3b2..16f7ad1123 100644 --- a/apps/client/src/widgets/layout/StatusBar.tsx +++ b/apps/client/src/widgets/layout/StatusBar.tsx @@ -56,7 +56,7 @@ export default function StatusBar() { similarNotesShown: activePane === "similar-notes", setSimilarNotesShown: (shown) => setActivePane(shown && "similar-notes") }; - const isHiddenNote = note?.isInHiddenSubtree(); + const isHiddenNote = note?.isHiddenCompletely(); return (
@@ -212,8 +212,8 @@ export function getLocaleName(locale: Locale | null | undefined) { //#region Note info & Similar interface NoteInfoContext extends StatusBarContext { - similarNotesShown: boolean; - setSimilarNotesShown: (value: boolean) => void; + similarNotesShown?: boolean; + setSimilarNotesShown?: (value: boolean) => void; } export function NoteInfoBadge(context: NoteInfoContext) { @@ -225,7 +225,7 @@ export function NoteInfoBadge(context: NoteInfoContext) { // Keyboard shortcut. useTriliumEvent("toggleRibbonTabNoteInfo", () => enabled && dropdownRef.current?.show()); - useTriliumEvent("toggleRibbonTabSimilarNotes", () => setSimilarNotesShown(!similarNotesShown)); + useTriliumEvent("toggleRibbonTabSimilarNotes", () => setSimilarNotesShown && setSimilarNotesShown(!similarNotesShown)); return (enabled && ; +export function NoteInfoContent({ note, setSimilarNotesShown, noteType, dropdownRef }: Pick & { + dropdownRef?: RefObject; noteType: NoteType; }) { const { metadata, ...sizeProps } = useNoteMetadata(note); @@ -251,7 +251,7 @@ function NoteInfoContent({ note, setSimilarNotesShown, noteType, dropdownRef }: const noteTypeMapping = useMemo(() => NOTE_TYPES.find(t => t.type === noteType), [ noteType ]); return ( - <> +
    {originalFileName && } @@ -262,14 +262,14 @@ function NoteInfoContent({ note, setSimilarNotesShown, noteType, dropdownRef }: } />
- { - dropdownRef.current?.hide(); + dropdownRef?.current?.hide(); setSimilarNotesShown(true); }} - /> - + />} +
); } @@ -300,7 +300,7 @@ function BacklinksBadge({ note, viewScope }: StatusBarContext) { const count = useBacklinkCount(note, viewScope?.viewMode === "default"); return (note && count > 0 && (null); const sortedNotePaths = useSortedNotePaths(note, hoistedNoteId); const count = sortedNotePaths?.length ?? 0; - const enabled = count > 1; + const enabled = true; // Keyboard shortcut. useTriliumEvent("toggleRibbonTabNotePaths", () => enabled && dropdownRef.current?.show()); diff --git a/apps/client/src/widgets/mobile_widgets/TabSwitcher.css b/apps/client/src/widgets/mobile_widgets/TabSwitcher.css index f401ee61b0..58b6c1fbc3 100644 --- a/apps/client/src/widgets/mobile_widgets/TabSwitcher.css +++ b/apps/client/src/widgets/mobile_widgets/TabSwitcher.css @@ -35,11 +35,6 @@ display: flex; flex-direction: column; - &.with-hue { - background-color: hsl(var(--bg-hue), 8.8%, 11.2%); - border-color: hsl(var(--bg-hue), 9.4%, 25.1%); - } - &.active { outline: 4px solid var(--more-accented-background-color); background: var(--card-background-hover-color); @@ -89,12 +84,25 @@ &.type-text { padding: 10px; + --ck-content-todo-list-checkmark-size: 8px; + + p { margin-bottom: 0.2em;} + hr { margin-block: 0.1em; height: 1px; } + h2 { font-size: 1.20em; } + h3 { font-size: 1.15em; } + h4 { font-size: 1.10em; } + h5 { font-size: 1.05em} + h6 { font-size: 1em; } + ul, ol { margin: 0 } } &.type-book, &.type-contentWidget, &.type-search, - &.type-empty { + &.type-empty, + &.type-relationMap, + &.type-launcher, + &.tab-preview-placeholder { display: flex; align-items: center; justify-content: center; @@ -105,13 +113,6 @@ .preview-placeholder { font-size: 500%; } - - p { margin-bottom: 0.2em;} - h2 { font-size: 1.20em; } - h3 { font-size: 1.15em; } - h4 { font-size: 1.10em; } - h5 { font-size: 1.05em} - h6 { font-size: 1em; } } &.with-split { diff --git a/apps/client/src/widgets/mobile_widgets/TabSwitcher.tsx b/apps/client/src/widgets/mobile_widgets/TabSwitcher.tsx index 6ee84f0465..ff92b6512e 100644 --- a/apps/client/src/widgets/mobile_widgets/TabSwitcher.tsx +++ b/apps/client/src/widgets/mobile_widgets/TabSwitcher.tsx @@ -1,6 +1,7 @@ import "./TabSwitcher.css"; import clsx from "clsx"; +import { ComponentChild } from "preact"; import { createPortal, Fragment } from "preact/compat"; import { useCallback, useEffect, useRef, useState } from "preact/hooks"; @@ -11,6 +12,7 @@ import contextMenu from "../../menus/context_menu"; import { getHue, parseColor } from "../../services/css_class_manager"; import froca from "../../services/froca"; import { t } from "../../services/i18n"; +import type { ViewMode, ViewScope } from "../../services/link"; import { NoteContent } from "../collections/legacy/ListOrGridView"; import { LaunchBarActionButton } from "../launch_bar/launch_bar_widgets"; import { ICON_MAPPINGS } from "../note_bars/CollectionProperties"; @@ -20,6 +22,13 @@ import Icon from "../react/Icon"; import LinkButton from "../react/LinkButton"; import Modal from "../react/Modal"; +const VIEW_MODE_ICON_MAPPINGS: Record, string> = { + source: "bx bx-code", + "contextual-help": "bx bx-help-circle", + "note-map": "bx bxs-network-chart", + attachments: "bx bx-paperclip", +}; + export default function TabSwitcher() { const [ shown, setShown ] = useState(false); const mainNoteContexts = useMainNoteContexts(); @@ -138,7 +147,6 @@ function Tab({ noteContext, containerRef, selectTab, activeNtxId }: { activeNtxId: string | null | undefined; }) { const { note } = noteContext; - const iconClass = useNoteIcon(note); const colorClass = note?.getColorClass() || ''; const workspaceTabBackgroundColorHue = getWorkspaceTabBackgroundColorHue(noteContext); const subContexts = noteContext.getSubContexts(); @@ -158,46 +166,65 @@ function Tab({ noteContext, containerRef, selectTab, activeNtxId }: { > {subContexts.map(subContext => ( -
- {subContext.note && } - {subContext.note?.title ?? t("tab_row.new_tab")} - {subContext.isMainContext() && { - // We are closing a tab, so we need to prevent propagation for click (activate tab). - e.stopPropagation(); - appContext.tabManager.removeNoteContext(subContext.ntxId); - }} - />} -
-
- -
+ +
))}
); } -function TabPreviewContent({ note }: { - note: FNote | null -}) { - if (!note) { - return ; - } +function TabHeader({ noteContext, colorClass }: { noteContext: NoteContext, colorClass: string }) { + const iconClass = useNoteIcon(noteContext.note); + const [ navigationTitle, setNavigationTitle ] = useState(null); - if (note.type === "book") { - return ; - } + // Manage the title for read-only notes + useEffect(() => { + noteContext?.getNavigationTitle().then(setNavigationTitle); + }, [noteContext]); return ( - + {noteContext.note && } + {navigationTitle ?? noteContext.note?.title ?? t("tab_row.new_tab")} + {noteContext.isMainContext() && { + // We are closing a tab, so we need to prevent propagation for click (activate tab). + e.stopPropagation(); + appContext.tabManager.removeNoteContext(noteContext.ntxId); + }} + />} + + ); +} + +function TabPreviewContent({ note, viewScope }: { + note: FNote | null, + viewScope: ViewScope | undefined +}) { + let el: ComponentChild; + let isPlaceholder = true; + + if (!note) { + el = ; + } else if (note.type === "book") { + el = ; + } else if (viewScope?.viewMode && viewScope.viewMode !== "default") { + el = ; + } else { + el = + />; + isPlaceholder = false; + } + + return ( +
{el}
); } diff --git a/apps/client/src/widgets/mobile_widgets/mobile_detail_menu.css b/apps/client/src/widgets/mobile_widgets/mobile_detail_menu.css new file mode 100644 index 0000000000..f3e1503471 --- /dev/null +++ b/apps/client/src/widgets/mobile_widgets/mobile_detail_menu.css @@ -0,0 +1,3 @@ +.code-note-switcher-modal .dropdown-menu { + background: none !important; +} diff --git a/apps/client/src/widgets/mobile_widgets/mobile_detail_menu.tsx b/apps/client/src/widgets/mobile_widgets/mobile_detail_menu.tsx index 1566d08890..909d3b6288 100644 --- a/apps/client/src/widgets/mobile_widgets/mobile_detail_menu.tsx +++ b/apps/client/src/widgets/mobile_widgets/mobile_detail_menu.tsx @@ -1,84 +1,240 @@ -import { useContext } from "preact/hooks"; +import "./mobile_detail_menu.css"; -import appContext, { CommandMappings } from "../../components/app_context"; -import contextMenu, { MenuItem } from "../../menus/context_menu"; -import branches from "../../services/branches"; +import { Dropdown as BootstrapDropdown } from "bootstrap"; +import { createPortal, useRef, useState } from "preact/compat"; + +import FNote, { NotePathRecord } from "../../entities/fnote"; import { t } from "../../services/i18n"; -import { getHelpUrlForNote } from "../../services/in_app_help"; import note_create from "../../services/note_create"; -import tree from "../../services/tree"; -import { openInAppHelpFromUrl } from "../../services/utils"; -import BasicWidget from "../basic_widget"; +import server from "../../services/server"; +import { BacklinksList, useBacklinkCount } from "../FloatingButtonsDefinitions"; +import { getLocaleName, NoteInfoContent } from "../layout/StatusBar"; import ActionButton from "../react/ActionButton"; -import { ParentComponent } from "../react/react_utils"; +import { FormDropdownDivider, FormDropdownSubmenu, FormListItem } from "../react/FormList"; +import { useNoteContext, useNoteProperty } from "../react/hooks"; +import Modal from "../react/Modal"; +import { NoteTypeCodeNoteList, useLanguageSwitcher, useMimeTypes } from "../ribbon/BasicPropertiesTab"; +import { NoteContextMenu } from "../ribbon/NoteActions"; +import NoteActionsCustom from "../ribbon/NoteActionsCustom"; +import { NotePathsWidget, useSortedNotePaths } from "../ribbon/NotePathsTab"; +import SimilarNotesTab from "../ribbon/SimilarNotesTab"; +import { useProcessedLocales } from "../type_widgets/options/components/LocaleSelector"; export default function MobileDetailMenu() { - const parentComponent = useContext(ParentComponent); + const dropdownRef = useRef(null); + const { note, noteContext, parentComponent, ntxId, viewScope, hoistedNoteId } = useNoteContext(); + const subContexts = noteContext?.getMainContext().getSubContexts() ?? []; + const isMainContext = noteContext?.isMainContext(); + const [ backlinksModalShown, setBacklinksModalShown ] = useState(false); + const [ notePathsModalShown, setNotePathsModalShown ] = useState(false); + const [ noteInfoModalShown, setNoteInfoModalShown ] = useState(false); + const [ similarNotesModalShown, setSimilarNotesModalShown ] = useState(false); + const [ codeNoteSwitcherModalShown, setCodeNoteSwitcherModalShown ] = useState(false); + const sortedNotePaths = useSortedNotePaths(note, hoistedNoteId); + const backlinksCount = useBacklinkCount(note, viewScope?.viewMode === "default"); + + function closePane() { + // Wait first for the context menu to be dismissed, otherwise the backdrop stays on. + requestAnimationFrame(() => { + parentComponent.triggerCommand("closeThisNoteSplit", { ntxId }); + }); + } return ( - { - const ntxId = (parentComponent as BasicWidget | null)?.getClosestNtxId(); - if (!ntxId) return; +
+ {note ? ( + +
+
+ setBacklinksModalShown(true)} + disabled={backlinksCount === 0} + >{t("status_bar.backlinks", { count: backlinksCount })} +
+
+ setNotePathsModalShown(true)} + disabled={(sortedNotePaths?.length ?? 0) <= 1} + >{t("status_bar.note_paths", { count: sortedNotePaths?.length })} +
+
+ - const noteContext = appContext.tabManager.getNoteContextById(ntxId); - const subContexts = noteContext.getMainContext().getSubContexts(); - const isMainContext = noteContext?.isMainContext(); - const note = noteContext.note; - const helpUrl = getHelpUrlForNote(note); + {noteContext && ntxId && } + noteContext?.notePath && note_create.createNote(noteContext.notePath)} + icon="bx bx-plus" + >{t("mobile_detail_menu.insert_child_note")} + {subContexts.length < 2 && <> + + { + // We have to manually manage the hide because otherwise the old note context gets activated. + e.stopPropagation(); + dropdownRef.current?.hide(); + parentComponent.triggerCommand("openNewNoteSplit", { ntxId }); + }} + icon="bx bx-dock-right" + >{t("create_pane_button.create_new_split")} + } + {!isMainContext && <> + + {t("close_pane_button.close_this_pane")} + } + + } + itemsNearNoteSettings={<> + {note.type === "text" && } + {note.type === "code" && setCodeNoteSwitcherModalShown(true)}>{t("status_bar.code_note_switcher")}} + setNoteInfoModalShown(true)}>{t("note_info_widget.title")} + setSimilarNotesModalShown(true)}>{t("similar_notes.title")} + + } + /> + ) : ( + + )} - const items: (MenuItem)[] = [ - { title: t("mobile_detail_menu.insert_child_note"), command: "insertChildNote", uiIcon: "bx bx-plus", enabled: note?.type !== "search" }, - { title: t("mobile_detail_menu.delete_this_note"), command: "delete", uiIcon: "bx bx-trash", enabled: note?.noteId !== "root" }, - { kind: "separator" }, - { title: t("mobile_detail_menu.note_revisions"), command: "showRevisions", uiIcon: "bx bx-history" }, - { kind: "separator" }, - helpUrl && { - title: t("help-button.title"), - uiIcon: "bx bx-help-circle", - handler: () => openInAppHelpFromUrl(helpUrl) - }, - { kind: "separator" }, - subContexts.length < 2 && { title: t("create_pane_button.create_new_split"), command: "openNewNoteSplit", uiIcon: "bx bx-dock-right" }, - !isMainContext && { title: t("close_pane_button.close_this_pane"), command: "closeThisNoteSplit", uiIcon: "bx bx-x" } - ].filter(i => !!i) as MenuItem[]; - - const lastItem = items.at(-1); - if (lastItem && "kind" in lastItem && lastItem.kind === "separator") { - items.pop(); - } - - contextMenu.show({ - x: e.pageX, - y: e.pageY, - items, - selectMenuItemHandler: async ({ command }) => { - if (command === "insertChildNote") { - note_create.createNote(appContext.tabManager.getActiveContextNotePath() ?? undefined); - } else if (command === "delete") { - const notePath = appContext.tabManager.getActiveContextNotePath(); - if (!notePath) { - throw new Error("Cannot get note path to delete."); - } - - const branchId = await tree.getBranchIdFromUrl(notePath); - - if (!branchId) { - throw new Error(t("mobile_detail_menu.error_cannot_get_branch_id", { notePath })); - } - - if (await branches.deleteNotes([branchId]) && parentComponent) { - parentComponent.triggerCommand("setActiveScreen", { screen: "tree" }); - } - } else if (command && parentComponent) { - parentComponent.triggerCommand(command, { ntxId }); - } - }, - forcePositionOnMobile: true - }); - }} - /> + {createPortal(( + <> + + + + + + + ), document.body)} +
+ ); +} + +function ContentLanguageSelector({ note }: { note: FNote | null | undefined }) { + const { locales, DEFAULT_LOCALE, currentNoteLanguage, setCurrentNoteLanguage } = useLanguageSwitcher(note); + const { activeLocale, processedLocales } = useProcessedLocales(locales, DEFAULT_LOCALE, currentNoteLanguage ?? DEFAULT_LOCALE.id); + + return ( + + {processedLocales.map((locale, index) => + (typeof locale === "object") ? ( + setCurrentNoteLanguage(locale.id)} + >{locale.name} + ) : ( + + ) + )} + + ); +} + +interface WithModal { + modalShown: boolean; + setModalShown: (shown: boolean) => void; +} + +function BacklinksModal({ note, modalShown, setModalShown }: { note: FNote | null | undefined } & WithModal) { + return ( + setModalShown(false)} + > +
    + {note && } +
+
+ ); +} + +function NotePathsModal({ note, modalShown, notePath, sortedNotePaths, setModalShown }: { note: FNote | null | undefined, sortedNotePaths: NotePathRecord[] | undefined, notePath: string | null | undefined } & WithModal) { + return ( + setModalShown(false)} + > + {note && ( + + )} + + ); +} + +function NoteInfoModal({ note, modalShown, setModalShown }: { note: FNote | null | undefined } & WithModal) { + return ( + setModalShown(false)} + > + {note && } + + ); +} + +function SimilarNotesModal({ note, modalShown, setModalShown }: { note: FNote | null | undefined } & WithModal) { + return ( + setModalShown(false)} + > + + + ); +} + +function CodeNoteSwitcherModal({ note, modalShown, setModalShown }: { note: FNote | null | undefined } & WithModal) { + const currentNoteMime = useNoteProperty(note, "mime"); + const mimeTypes = useMimeTypes(); + + return ( + setModalShown(false)} + > +
+ {note && { + server.put(`notes/${note.noteId}/type`, { type, mime }); + setModalShown(false); + }} + />} +
+
); } diff --git a/apps/client/src/widgets/mobile_widgets/sidebar_container.ts b/apps/client/src/widgets/mobile_widgets/sidebar_container.ts index ef719d36a9..f79d8a72c2 100644 --- a/apps/client/src/widgets/mobile_widgets/sidebar_container.ts +++ b/apps/client/src/widgets/mobile_widgets/sidebar_container.ts @@ -13,7 +13,7 @@ const DRAG_OPEN_THRESHOLD = 10; /** The number of pixels the user has to drag across the screen to the right when the sidebar is closed to trigger the drag open animation. */ const DRAG_CLOSED_START_THRESHOLD = 10; /** The number of pixels the user has to drag across the screen to the left when the sidebar is opened to trigger the drag close animation. */ -const DRAG_OPENED_START_THRESHOLD = 80; +const DRAG_OPENED_START_THRESHOLD = 100; export default class SidebarContainer extends FlexContainer { private screenName: Screen; @@ -54,7 +54,7 @@ export default class SidebarContainer extends FlexContainer { this.startX = x; // Prevent dragging if too far from the edge of the screen and the menu is closed. - let dragRefX = glob.isRtl ? this.screenWidth - x : x; + const dragRefX = glob.isRtl ? this.screenWidth - x : x; if (dragRefX > 30 && this.currentTranslate === -100) { return; } @@ -89,7 +89,7 @@ export default class SidebarContainer extends FlexContainer { } } else if (this.dragState === DRAG_STATE_DRAGGING) { const width = this.sidebarEl.offsetWidth; - let translatePercentage = Math.min(0, Math.max(this.currentTranslate + (deltaX / width) * 100, -100)); + const translatePercentage = Math.min(0, Math.max(this.currentTranslate + (deltaX / width) * 100, -100)); const backdropOpacity = Math.max(0, 1 + translatePercentage / 100); this.translatePercentage = translatePercentage; if (glob.isRtl) { @@ -160,12 +160,10 @@ export default class SidebarContainer extends FlexContainer { this.sidebarEl.classList.toggle("show", isOpen); if (isOpen) { this.sidebarEl.style.transform = "translateX(0)"; + } else if (glob.isRtl) { + this.sidebarEl.style.transform = "translateX(100%)"; } else { - if (glob.isRtl) { - this.sidebarEl.style.transform = "translateX(100%)" - } else { - this.sidebarEl.style.transform = "translateX(-100%)"; - } + this.sidebarEl.style.transform = "translateX(-100%)"; } this.sidebarEl.style.transition = this.originalSidebarTransition; diff --git a/apps/client/src/widgets/mobile_widgets/toggle_sidebar_button.tsx b/apps/client/src/widgets/mobile_widgets/toggle_sidebar_button.tsx index 8e689954b0..b87e8cb90e 100644 --- a/apps/client/src/widgets/mobile_widgets/toggle_sidebar_button.tsx +++ b/apps/client/src/widgets/mobile_widgets/toggle_sidebar_button.tsx @@ -1,5 +1,5 @@ -import ActionButton from "../react/ActionButton"; import { t } from "../../services/i18n"; +import ActionButton from "../react/ActionButton"; import { useNoteContext } from "../react/hooks"; export default function ToggleSidebarButton() { @@ -10,10 +10,15 @@ export default function ToggleSidebarButton() { { noteContext?.isMainContext() && parentComponent?.triggerCommand("setActiveScreen", { - screen: "tree" - })} + onClick={(e) => { + // Remove focus to prevent tooltip showing on top of the sidebar. + (e.currentTarget as HTMLButtonElement).blur(); + + parentComponent?.triggerCommand("setActiveScreen", { + screen: "tree" + }); + }} />}
- ) + ); } diff --git a/apps/client/src/widgets/note_bars/CollectionProperties.css b/apps/client/src/widgets/note_bars/CollectionProperties.css index 99700f77a7..c8802a42a0 100644 --- a/apps/client/src/widgets/note_bars/CollectionProperties.css +++ b/apps/client/src/widgets/note_bars/CollectionProperties.css @@ -5,7 +5,7 @@ align-items: center; width: 100%; max-width: unset; - font-size: 0.8em; + font-size: 0.8rem; .dropdown-menu { input.form-control { diff --git a/apps/client/src/widgets/note_bars/CollectionProperties.tsx b/apps/client/src/widgets/note_bars/CollectionProperties.tsx index 5dba675e6d..66bfb32c45 100644 --- a/apps/client/src/widgets/note_bars/CollectionProperties.tsx +++ b/apps/client/src/widgets/note_bars/CollectionProperties.tsx @@ -2,18 +2,16 @@ import "./CollectionProperties.css"; import { t } from "i18next"; import { ComponentChildren } from "preact"; -import { useContext, useRef } from "preact/hooks"; -import { Fragment } from "preact/jsx-runtime"; +import { useRef } from "preact/hooks"; import FNote from "../../entities/fnote"; import { ViewTypeOptions } from "../collections/interface"; import Dropdown from "../react/Dropdown"; -import { FormDropdownDivider, FormDropdownSubmenu, FormListItem, FormListToggleableItem } from "../react/FormList"; -import FormTextBox from "../react/FormTextBox"; -import { useNoteLabel, useNoteLabelBoolean, useNoteLabelWithDefault, useNoteProperty, useTriliumEvent } from "../react/hooks"; +import { FormDropdownDivider, FormListItem } from "../react/FormList"; +import { useNoteProperty, useTriliumEvent } from "../react/hooks"; import Icon from "../react/Icon"; -import { ParentComponent } from "../react/react_utils"; -import { bookPropertiesConfig, BookProperty, ButtonProperty, CheckBoxProperty, ComboBoxItem, ComboBoxProperty, NumberProperty, SplitButtonProperty } from "../ribbon/collection-properties-config"; +import { CheckBoxProperty, ViewProperty } from "../react/NotePropertyMenu"; +import { bookPropertiesConfig } from "../ribbon/collection-properties-config"; import { useViewType, VIEW_TYPE_MAPPINGS } from "../ribbon/CollectionPropertiesTab"; export const ICON_MAPPINGS: Record = { @@ -85,9 +83,11 @@ function ViewOptions({ note, viewType }: { note: FNote, viewType: ViewTypeOption - {properties.map(property => ( - + {properties.map((property, index) => ( + ))} {properties.length > 0 && } @@ -107,127 +107,3 @@ function ViewOptions({ note, viewType }: { note: FNote, viewType: ViewTypeOption ); } - -function ViewProperty({ note, property }: { note: FNote, property: BookProperty }) { - switch (property.type) { - case "button": - return ; - case "split-button": - return ; - case "checkbox": - return ; - case "number": - return ; - case "combobox": - return ; - } -} - -function ButtonPropertyView({ note, property }: { note: FNote, property: ButtonProperty }) { - const parentComponent = useContext(ParentComponent); - - return ( - { - if (!parentComponent) return; - property.onClick({ - note, - triggerCommand: parentComponent.triggerCommand.bind(parentComponent) - }); - }} - >{property.label} - ); -} - -function SplitButtonPropertyView({ note, property }: { note: FNote, property: SplitButtonProperty }) { - const parentComponent = useContext(ParentComponent); - const ItemsComponent = property.items; - const clickContext = parentComponent && { - note, - triggerCommand: parentComponent.triggerCommand.bind(parentComponent) - }; - - return (parentComponent && - clickContext && property.onClick(clickContext)} - > - - - ); -} - -function NumberPropertyView({ note, property }: { note: FNote, property: NumberProperty }) { - //@ts-expect-error Interop with text box which takes in string values even for numbers. - const [ value, setValue ] = useNoteLabel(note, property.bindToLabel); - const disabled = property.disabled?.(note); - - return ( - e.stopPropagation()} - > - {property.label} - - - ); -} - -function ComboBoxPropertyView({ note, property }: { note: FNote, property: ComboBoxProperty }) { - const [ value, setValue ] = useNoteLabelWithDefault(note, property.bindToLabel, property.defaultValue ?? ""); - - function renderItem(option: ComboBoxItem) { - return ( - setValue(option.value)} - > - {option.label} - - ); - } - - return ( - - {(property.options).map((option, index) => { - if ("items" in option) { - return ( - - {option.title} - {option.items.map(renderItem)} - {index < property.options.length - 1 && } - - ); - } - return renderItem(option); - - })} - - ); -} - -function CheckBoxPropertyView({ note, property }: { note: FNote, property: CheckBoxProperty }) { - const [ value, setValue ] = useNoteLabelBoolean(note, property.bindToLabel); - return ( - - ); -} diff --git a/apps/client/src/widgets/note_icon.css b/apps/client/src/widgets/note_icon.css index 4ed6df6482..cea05cdcd9 100644 --- a/apps/client/src/widgets/note_icon.css +++ b/apps/client/src/widgets/note_icon.css @@ -117,3 +117,35 @@ body.experimental-feature-new-layout { } } } + +body.mobile .modal.icon-switcher { + .modal-dialog { + left: 0; + right: 0; + margin: unset; + transform: unset; + max-width: 100%; + height: 100%; + } + + .modal-body { + padding: 0; + display: flex; + flex-direction: column; + + > .filter-row { + padding: 0.25em var(--bs-modal-padding) 0.5em var(--bs-modal-padding); + border-bottom: 1px solid var(--main-border-color); + } + } + + .icon-list { + margin: auto; + flex-grow: 1; + height: 100%; + + span { + padding: 12px; + } + } +} diff --git a/apps/client/src/widgets/note_icon.tsx b/apps/client/src/widgets/note_icon.tsx index 51204b015e..31ca7e65b4 100644 --- a/apps/client/src/widgets/note_icon.tsx +++ b/apps/client/src/widgets/note_icon.tsx @@ -4,7 +4,8 @@ import { IconRegistry } from "@triliumnext/commons"; import { Dropdown as BootstrapDropdown } from "bootstrap"; import clsx from "clsx"; import { t } from "i18next"; -import { CSSProperties, RefObject } from "preact"; +import { CSSProperties } from "preact"; +import { createPortal } from "preact/compat"; import { useEffect, useMemo, useRef, useState } from "preact/hooks"; import type React from "react"; import { CellComponentProps, Grid } from "react-window"; @@ -12,11 +13,15 @@ import { CellComponentProps, Grid } from "react-window"; import FNote from "../entities/fnote"; import attributes from "../services/attributes"; import server from "../services/server"; +import { isDesktop, isMobile } from "../services/utils"; import ActionButton from "./react/ActionButton"; import Dropdown from "./react/Dropdown"; import { FormDropdownDivider, FormListItem } from "./react/FormList"; import FormTextBox from "./react/FormTextBox"; -import { useNoteContext, useNoteLabel, useStaticTooltip } from "./react/hooks"; +import { useNoteContext, useNoteLabel, useStaticTooltip, useWindowSize } from "./react/hooks"; +import Modal from "./react/Modal"; + +const ICON_SIZE = isMobile() ? 56 : 48; interface IconToCountCache { iconClassToCountMap: Record; @@ -37,6 +42,10 @@ export default function NoteIcon() { setIcon(note?.getIcon()); }, [ note, iconClass, workspaceIconClass ]); + if (isMobile()) { + return ; + } + return ( - { note && } + { note && dropdownRef?.current?.hide()} columnCount={12} /> } ); } -function NoteIconList({ note, dropdownRef }: { - note: FNote, - dropdownRef: RefObject; +function MobileNoteIconSwitcher({ note, icon }: { + note: FNote | null | undefined; + icon: string | null | undefined; +}) { + const [ modalShown, setModalShown ] = useState(false); + const { windowWidth } = useWindowSize(); + + return ( +
+ setModalShown(true)} + /> + + {createPortal(( + setModalShown(false)} + className="icon-switcher note-icon-widget" + scrollable + > + {note && setModalShown(false)} columnCount={Math.max(1, Math.floor(windowWidth / ICON_SIZE))} />} + + ), document.body)} +
+ ); +} + +function NoteIconList({ note, onHide, columnCount }: { + note: FNote; + onHide: () => void; + columnCount: number; }) { - const searchBoxRef = useRef(null); const iconListRef = useRef(null); const [ search, setSearch ] = useState(); const [ filterByPrefix, setFilterByPrefix ] = useState(null); @@ -73,53 +113,22 @@ function NoteIconList({ note, dropdownRef }: { return ( <> -
- {t("note_icon.search")} - s.prefix === filterByPrefix)?.name ?? "" - }) - : t("note_icon.search_placeholder", { number: filteredIcons.length ?? 0, count: glob.iconRegistry.sources.length })} - currentValue={search} onChange={setSearch} - autoFocus - /> - - {getIconLabels(note).length > 0 && ( -
- { - if (!note) return; - for (const label of getIconLabels(note)) { - attributes.removeAttributeById(note.noteId, label.attributeId); - } - dropdownRef?.current?.hide(); - }} - /> -
- )} - - {glob.iconRegistry.sources.length > 0 && - - } -
+
{ // Make sure we are not clicking on something else than a button. const clickedTarget = e.target as HTMLElement; @@ -130,18 +139,19 @@ function NoteIconList({ note, dropdownRef }: { const attributeToSet = note.hasOwnedLabel("workspace") ? "workspaceIconClass" : "iconClass"; attributes.setLabel(note.noteId, attributeToSet, iconClass); } - dropdownRef?.current?.hide(); + onHide(); }} > {filteredIcons.length ? ( ) : ( @@ -152,10 +162,95 @@ function NoteIconList({ note, dropdownRef }: { ); } -function IconItemCell({ rowIndex, columnIndex, style, filteredIcons }: CellComponentProps<{ +function FilterRow({ note, filterByPrefix, search, setSearch, setFilterByPrefix, filteredIcons, onHide }: { + note: FNote; + filterByPrefix: string | null; + search: string | undefined; + setSearch: (value: string | undefined) => void; + setFilterByPrefix: (value: string | null) => void; filteredIcons: IconWithName[]; + onHide: () => void; +}) { + const searchBoxRef = useRef(null); + const hasCustomIcon = getIconLabels(note).length > 0; + + function resetToDefaultIcon() { + if (!note) return; + for (const label of getIconLabels(note)) { + attributes.removeAttributeById(note.noteId, label.attributeId); + } + onHide(); + } + + return ( +
+ {t("note_icon.search")} + s.prefix === filterByPrefix)?.name ?? "" + }) + : t("note_icon.search_placeholder", { number: filteredIcons.length ?? 0, count: glob.iconRegistry.sources.length })} + currentValue={search} onChange={setSearch} + autoFocus + /> + + {isDesktop() + ? <> + {hasCustomIcon && ( +
+ +
+ )} + + { + + } + : ( + + {hasCustomIcon && <> + {t("note_icon.reset-default")} + + } + + + + )} +
+ ); +} + +function IconItemCell({ rowIndex, columnIndex, style, filteredIcons, columnCount }: CellComponentProps<{ + filteredIcons: IconWithName[]; + columnCount: number; }>) { - const iconIndex = rowIndex * 12 + columnIndex; + const iconIndex = rowIndex * columnCount + columnIndex; const iconData = filteredIcons[iconIndex] as IconWithName | undefined; if (!iconData) return <> as React.ReactElement; @@ -184,7 +279,7 @@ function IconFilterContent({ filterByPrefix, setFilterByPrefix }: { checked={filterByPrefix === "bx"} onClick={() => setFilterByPrefix("bx")} >{t("note_icon.filter-default")} - + {glob.iconRegistry.sources.length > 1 && } {glob.iconRegistry.sources.map(({ prefix, name, icon }) => ( prefix !== "bx" && 0) { const $badge = $(`${count}`); $badge.attr("title", t("note_tree.subtree-hidden-tooltip", { count })); - $span.find(".fancytree-title").append($badge); + $span.append($badge); } }; } diff --git a/apps/client/src/widgets/note_types.tsx b/apps/client/src/widgets/note_types.tsx index e58960d708..d0209bf5a2 100644 --- a/apps/client/src/widgets/note_types.tsx +++ b/apps/client/src/widgets/note_types.tsx @@ -43,7 +43,8 @@ export const TYPE_MAPPINGS: Record = { }, protectedSession: { view: () => import("./type_widgets/ProtectedSession"), - className: "protected-session-password-component" + className: "protected-session-password-component", + isFullHeight: true }, book: { view: () => import("./type_widgets/Book"), diff --git a/apps/client/src/widgets/react/ActionButton.tsx b/apps/client/src/widgets/react/ActionButton.tsx index feb5972ef4..764e155c44 100644 --- a/apps/client/src/widgets/react/ActionButton.tsx +++ b/apps/client/src/widgets/react/ActionButton.tsx @@ -3,6 +3,7 @@ import { useEffect, useRef, useState } from "preact/hooks"; import { CommandNames } from "../../components/app_context"; import keyboard_actions from "../../services/keyboard_actions"; +import { isMobile } from "../../services/utils"; import { useStaticTooltip } from "./hooks"; export interface ActionButtonProps extends Pick, "onClick" | "onAuxClick" | "onContextMenu" | "style"> { @@ -17,6 +18,8 @@ export interface ActionButtonProps extends Pick(null); const [ keyboardShortcut, setKeyboardShortcut ] = useState(); @@ -25,6 +28,7 @@ export default function ActionButton({ text, icon, className, triggerCommand, ti title: keyboardShortcut?.length ? `${text} (${keyboardShortcut?.join(",")})` : text, placement: titlePosition ?? "bottom", fallbackPlacements: [ titlePosition ?? "bottom" ], + trigger: cachedIsMobile ? "focus" : "hover focus", animation: false }); diff --git a/apps/client/src/widgets/react/Button.tsx b/apps/client/src/widgets/react/Button.tsx index ffdc6ddd2c..6269000563 100644 --- a/apps/client/src/widgets/react/Button.tsx +++ b/apps/client/src/widgets/react/Button.tsx @@ -1,13 +1,14 @@ -import type { ComponentChildren, RefObject } from "preact"; -import type { CSSProperties } from "preact/compat"; +import type { ComponentChildren, CSSProperties, RefObject } from "preact"; import { memo } from "preact/compat"; import { useMemo } from "preact/hooks"; import { CommandNames } from "../../components/app_context"; -import { isDesktop } from "../../services/utils"; +import { isDesktop, isMobile } from "../../services/utils"; import ActionButton from "./ActionButton"; import Icon from "./Icon"; +const cachedIsMobile = isMobile(); + export interface ButtonProps { name?: string; /** Reference to the button element. Mostly useful for requesting focus. */ @@ -18,7 +19,7 @@ export interface ButtonProps { keyboardShortcut?: string; /** Called when the button is clicked. If not set, the button will submit the form (if any). */ onClick?: () => void; - primary?: boolean; + kind?: "primary" | "secondary" | "lowProfile"; disabled?: boolean; size?: "normal" | "small" | "micro"; style?: CSSProperties; @@ -26,15 +27,23 @@ export interface ButtonProps { title?: string; } -const Button = memo(({ name, buttonRef, className, text, onClick, keyboardShortcut, icon, primary, disabled, size, style, triggerCommand, ...restProps }: ButtonProps) => { +const Button = memo(({ name, buttonRef, className, text, onClick, keyboardShortcut, icon, kind, disabled, size, style, triggerCommand, ...restProps }: ButtonProps) => { // Memoize classes array to prevent recreation const classes = useMemo(() => { const classList: string[] = ["btn"]; - if (primary) { - classList.push("btn-primary"); - } else { - classList.push("btn-secondary"); + + switch(kind) { + case "primary": + classList.push("btn-primary"); + break; + case "lowProfile": + classList.push("tn-low-profile"); + break; + default: + classList.push("btn-secondary"); + break; } + if (className) { classList.push(className); } @@ -44,11 +53,11 @@ const Button = memo(({ name, buttonRef, className, text, onClick, keyboardShortc classList.push("btn-micro"); } return classList.join(" "); - }, [primary, className, size]); + }, [kind, className, size]); // Memoize keyboard shortcut rendering const shortcutElements = useMemo(() => { - if (!keyboardShortcut) return null; + if (!keyboardShortcut || cachedIsMobile) return null; const splitShortcut = keyboardShortcut.split("+"); return splitShortcut.map((key, index) => ( <> diff --git a/apps/client/src/widgets/react/Card.css b/apps/client/src/widgets/react/Card.css new file mode 100644 index 0000000000..cabc4a0889 --- /dev/null +++ b/apps/client/src/widgets/react/Card.css @@ -0,0 +1,47 @@ +:where(.tn-card) { + --card-border-radius: 8px; + --card-padding-block: 8px; + --card-padding-inline: 16px; + --card-section-gap: 3px; + --card-nested-section-indent: 30px; +} + +.tn-card-heading { + margin-bottom: 10px; + font-size: .75rem; + font-weight: 600; + letter-spacing: .4pt; + text-transform: uppercase; +} + +.tn-card-body { + display: flex; + flex-direction: column; + gap: var(--card-section-gap); + + .tn-card-section { + padding: var(--card-padding-block) var(--card-padding-inline); + border: 1px solid var(--card-border-color, var(--main-border-color)); + background: var(--card-background-color); + + &:first-of-type { + border-top-left-radius: var(--card-border-radius); + border-top-right-radius: var(--card-border-radius); + } + + &:last-of-type { + border-bottom-left-radius: var(--card-border-radius); + border-bottom-right-radius: var(--card-border-radius); + } + + &.tn-card-section-nested { + padding-left: calc(var(--card-padding-inline) + var(--card-nested-section-indent) * var(--tn-card-section-nesting-level)); + background-color: color-mix(in srgb, var(--card-background-color) calc(100% / (var(--tn-card-section-nesting-level) + 1)) , transparent); + } + + &.tn-card-section-highlight-on-hover:hover { + background-color: var(--card-background-hover-color); + transition: background-color .2s ease-out; + } + } +} \ No newline at end of file diff --git a/apps/client/src/widgets/react/Card.tsx b/apps/client/src/widgets/react/Card.tsx new file mode 100644 index 0000000000..224a151504 --- /dev/null +++ b/apps/client/src/widgets/react/Card.tsx @@ -0,0 +1,63 @@ +import "./Card.css"; +import { ComponentChildren, createContext } from "preact"; +import { JSX } from "preact"; +import { useContext } from "preact/hooks"; +import clsx from "clsx"; + +// #region Card + +export interface CardProps { + className?: string; + heading?: string; +} + +export function Card(props: {children: ComponentChildren} & CardProps) { + return
+ {props.heading &&
{props.heading}
} +
+ {props.children} +
+
; +} + +// #endregion + +// #region Card Section + +export interface CardSectionProps { + className?: string; + subSections?: JSX.Element | JSX.Element[]; + subSectionsVisible?: boolean; + highlightOnHover?: boolean; + onAction?: () => void; +} + +interface CardSectionContextType { + nestingLevel: number; +} + +const CardSectionContext = createContext(undefined); + +export function CardSection(props: {children: ComponentChildren} & CardSectionProps) { + const parentContext = useContext(CardSectionContext); + const nestingLevel = (parentContext && parentContext.nestingLevel + 1) ?? 0; + + return <> +
0, + "tn-card-section-highlight-on-hover": props.highlightOnHover || props.onAction + })} + style={{"--tn-card-section-nesting-level": (nestingLevel) ? nestingLevel : null}} + onClick={props.onAction}> + {props.children} +
+ + {props.subSectionsVisible && props.subSections && + + {props.subSections} + + } + ; +} + +// #endregion \ No newline at end of file diff --git a/apps/client/src/widgets/react/Collapsible.css b/apps/client/src/widgets/react/Collapsible.css index 7dca2f5651..00aeb2bf7a 100644 --- a/apps/client/src/widgets/react/Collapsible.css +++ b/apps/client/src/widgets/react/Collapsible.css @@ -3,10 +3,7 @@ line-height: 1em; display: flex; align-items: center; - appearance: none; - background: transparent; - border: 0; - color: inherit; + padding-inline-end: 12px; .arrow { font-size: 1.3em; @@ -17,21 +14,34 @@ .collapsible-body { height: 0; overflow: hidden; + + &.fully-expanded { + overflow: visible; + } } .collapsible-inner-body { padding-top: 0.5em; + opacity: 0; } &.expanded { .collapsible-title .arrow { transform: rotate(90deg); } + + .collapsible-inner-body { + opacity: 1; + } } &.with-transition { .collapsible-body { transition: height 250ms ease-in; } + + .collapsible-inner-body { + transition: opacity 250ms ease-in; + } } } diff --git a/apps/client/src/widgets/react/Collapsible.tsx b/apps/client/src/widgets/react/Collapsible.tsx index a6e1957b34..cdbd0dcac5 100644 --- a/apps/client/src/widgets/react/Collapsible.tsx +++ b/apps/client/src/widgets/react/Collapsible.tsx @@ -27,6 +27,7 @@ export function ExternallyControlledCollapsible({ title, children, className, ex const { height } = useElementSize(innerRef) ?? {}; const contentId = useUniqueName(); const [ transitionEnabled, setTransitionEnabled ] = useState(false); + const [ fullyExpanded, setFullyExpanded ] = useState(false); useEffect(() => { const timeout = setTimeout(() => { @@ -35,13 +36,28 @@ export function ExternallyControlledCollapsible({ title, children, className, ex return () => clearTimeout(timeout); }, []); + useEffect(() => { + if (expanded) { + if (transitionEnabled) { + const timeout = setTimeout(() => { + setFullyExpanded(true); + }, 250); + return () => clearTimeout(timeout); + } else { + setFullyExpanded(true); + } + } else { + setFullyExpanded(false); + } + }, [expanded, transitionEnabled]) + return (
- - - + )}
@@ -162,6 +140,56 @@ export default function SearchDefinitionTab({ note, ntxId, hidden }: Pick("special-notes/save-search-note", { searchNoteId: note.noteId }); + if (!notePath) return; + + await ws.waitForMaxKnownEntityChangeId(); + await appContext.tabManager.getActiveContext()?.setNote(notePath); + + // Note the {{- notePathTitle}} in json file is not typo, it's unescaping + // See https://www.i18next.com/translation-function/interpolation#unescape + toast.showMessage(t("search_definition.search_note_saved", { notePathTitle: await tree.getNotePathTitle(notePath) })); + } + + return ( + + + + +
+ } + mobile={ + + {t("search_definition.search_execute")} + {note.isHiddenCompletely() && {t("search_definition.save_to_note")}} + + } + /> + + + + ); +} + function BulkActionsList({ note }: { note: FNote }) { const [ bulkActions, setBulkActions ] = useState(); @@ -194,15 +222,18 @@ function AddBulkActionButton({ note }: { note: FNote }) { buttonClassName="action-add-toggle btn btn-sm" text={<>{" "}{t("search_definition.action")}} noSelectButtonStyle + dropdownContainerClassName="mobile-bottom-menu" mobileBackdrop > - {ACTION_GROUPS.map(({ actions, title }) => ( - <> + {ACTION_GROUPS.map(({ actions, title }, index) => ( + - {actions.map(({ actionName, actionTitle }) => ( - bulk_action.addAction(note.noteId, actionName)}>{actionTitle} - ))} - +
+ {actions.map(({ actionName, actionTitle }) => ( + bulk_action.addAction(note.noteId, actionName)}>{actionTitle} + ))} +
+
))} ); diff --git a/apps/client/src/widgets/ribbon/SimilarNotesTab.css b/apps/client/src/widgets/ribbon/SimilarNotesTab.css new file mode 100644 index 0000000000..560f2da0ce --- /dev/null +++ b/apps/client/src/widgets/ribbon/SimilarNotesTab.css @@ -0,0 +1,4 @@ +.similar-notes-widget > .similar-notes-wrapper { + /* The font size of the links with the highest similarity score */ + font-size: 17px; +} \ No newline at end of file diff --git a/apps/client/src/widgets/ribbon/SimilarNotesTab.tsx b/apps/client/src/widgets/ribbon/SimilarNotesTab.tsx index c8dc1337fe..809db0e55a 100644 --- a/apps/client/src/widgets/ribbon/SimilarNotesTab.tsx +++ b/apps/client/src/widgets/ribbon/SimilarNotesTab.tsx @@ -1,3 +1,5 @@ +import "./SimilarNotesTab.css"; + import { SimilarNoteResponse } from "@triliumnext/commons"; import { useEffect, useState } from "preact/hooks"; @@ -33,7 +35,7 @@ export default function SimilarNotesTab({ note }: Pick) { notePath={notePath} noTnLink style={{ - "font-size": 20 * (1 - 1 / (1 + score)) + "font-size": (1 - 1 / (1 + score)) + "em" }} /> ))} diff --git a/apps/client/src/widgets/ribbon/collection-properties-config.tsx b/apps/client/src/widgets/ribbon/collection-properties-config.tsx index 1f79217e9c..b4a46a89bc 100644 --- a/apps/client/src/widgets/ribbon/collection-properties-config.tsx +++ b/apps/client/src/widgets/ribbon/collection-properties-config.tsx @@ -1,79 +1,19 @@ import { t } from "i18next"; + +import Component from "../../components/component"; import FNote from "../../entities/fnote"; import attributes from "../../services/attributes"; -import NoteContextAwareWidget from "../note_context_aware_widget"; import { DEFAULT_MAP_LAYER_NAME, MAP_LAYERS, type MapLayer } from "../collections/geomap/map_layer"; import { ViewTypeOptions } from "../collections/interface"; -import { FilterLabelsByType } from "@triliumnext/commons"; import { DEFAULT_THEME, getPresentationThemes } from "../collections/presentation/themes"; -import { VNode } from "preact"; -import { useNoteLabel } from "../react/hooks"; import { FormDropdownDivider, FormListItem } from "../react/FormList"; -import Component from "../../components/component"; +import { useNoteLabel } from "../react/hooks"; +import { BookProperty, ClickContext, ComboBoxItem } from "../react/NotePropertyMenu"; interface BookConfig { properties: BookProperty[]; } -export interface CheckBoxProperty { - type: "checkbox", - label: string; - bindToLabel: FilterLabelsByType; - icon?: string; -} - -export interface ButtonProperty { - type: "button", - label: string; - title?: string; - icon?: string; - onClick(context: BookContext): void; -} - -export interface SplitButtonProperty extends Omit { - type: "split-button"; - items({ note, parentComponent }: { note: FNote, parentComponent: Component }): VNode; -} - -export interface NumberProperty { - type: "number", - label: string; - bindToLabel: FilterLabelsByType; - width?: number; - min?: number; - icon?: string; - disabled?: (note: FNote) => boolean; -} - -export interface ComboBoxItem { - value: string; - label: string; -} - -interface ComboBoxGroup { - title: string; - items: ComboBoxItem[]; -} - -export interface ComboBoxProperty { - type: "combobox", - label: string; - icon?: string; - bindToLabel: FilterLabelsByType; - /** - * The default value is used when the label is not set. - */ - defaultValue?: string; - options: (ComboBoxItem | ComboBoxGroup)[]; -} - -export type BookProperty = CheckBoxProperty | ButtonProperty | NumberProperty | ComboBoxProperty | SplitButtonProperty; - -interface BookContext { - note: FNote; - triggerCommand: NoteContextAwareWidget["triggerCommand"]; -} - export const bookPropertiesConfig: Record = { grid: { properties: [] @@ -156,6 +96,13 @@ export const bookPropertiesConfig: Record = { icon: "bx bx-ruler", type: "checkbox", bindToLabel: "map:scale" + }, + { + label: t("book_properties_config.show-labels"), + icon: "bx bx-label", + type: "checkbox", + bindToLabel: "map:hideLabels", + reverseValue: true } ] }, @@ -211,7 +158,7 @@ function ListExpandDepth(context: { note: FNote, parentComponent: Component }) { - ) + ); } function ListExpandDepthButton({ label, depth, note, parentComponent, checked }: { label: string, depth: number | "all", note: FNote, parentComponent: Component, checked?: boolean }) { @@ -226,7 +173,7 @@ function ListExpandDepthButton({ label, depth, note, parentComponent, checked }: } function buildExpandListHandler(depth: number | "all") { - return async ({ note, triggerCommand }: BookContext) => { + return async ({ note, triggerCommand }: ClickContext) => { const { noteId } = note; const existingValue = note.getLabelValue("expanded"); @@ -236,5 +183,5 @@ function buildExpandListHandler(depth: number | "all") { await attributes.setLabel(noteId, "expanded", newValue); triggerCommand("refreshNoteList", { noteId }); - } + }; } diff --git a/apps/client/src/widgets/tab_row.ts b/apps/client/src/widgets/tab_row.ts index b78952fafb..1089f49c9b 100644 --- a/apps/client/src/widgets/tab_row.ts +++ b/apps/client/src/widgets/tab_row.ts @@ -1,13 +1,14 @@ import Draggabilly, { type MoveVector } from "draggabilly"; -import { t } from "../services/i18n.js"; -import BasicWidget from "./basic_widget.js"; -import contextMenu from "../menus/context_menu.js"; -import utils from "../services/utils.js"; -import keyboardActionService from "../services/keyboard_actions.js"; -import appContext, { type CommandNames, type CommandListenerData, type EventData } from "../components/app_context.js"; -import froca from "../services/froca.js"; -import attributeService from "../services/attributes.js"; + +import appContext, { type CommandListenerData, type CommandNames, type EventData } from "../components/app_context.js"; import type NoteContext from "../components/note_context.js"; +import contextMenu from "../menus/context_menu.js"; +import attributeService from "../services/attributes.js"; +import froca from "../services/froca.js"; +import { t } from "../services/i18n.js"; +import keyboardActionService from "../services/keyboard_actions.js"; +import utils from "../services/utils.js"; +import BasicWidget from "./basic_widget.js"; import { setupHorizontalScrollViaWheel } from "./widget_utils.js"; const isDesktop = utils.isDesktop(); @@ -96,7 +97,6 @@ const TAB_ROW_TPL = ` .tab-row-filler { box-sizing: border-box; -webkit-app-region: drag; - height: 100%; min-width: ${MIN_FILLER_WIDTH}px; flex-grow: 1; } diff --git a/apps/client/src/widgets/type_widgets/Attachment.css b/apps/client/src/widgets/type_widgets/Attachment.css index 014a00b6e5..09bc5101ba 100644 --- a/apps/client/src/widgets/type_widgets/Attachment.css +++ b/apps/client/src/widgets/type_widgets/Attachment.css @@ -6,10 +6,16 @@ .attachment-list .links-wrapper { font-size: larger; - margin-bottom: 15px; + margin-block: 12px; display: flex; justify-content: space-between; align-items: baseline; + + @media (max-width: 991px) { + margin-block: 1em; + flex-direction: column; + gap: 0.5em; + } } /* #endregion */ @@ -42,6 +48,12 @@ display: flex; align-items: center; gap: 1em; + + @media (max-width: 991px) { + gap: 0.5em; + flex-wrap: wrap; + .attachment-title { flex-grow: 1; } + } } .attachment-details { @@ -127,10 +139,6 @@ /* #region Attachment actions */ -.attachment-actions .dropdown-menu { - width: 20em; -} - .attachment-actions .dropdown-item .tn-icon { position: relative; top: 3px; diff --git a/apps/client/src/widgets/type_widgets/Attachment.tsx b/apps/client/src/widgets/type_widgets/Attachment.tsx index 95bc3c340c..041814589c 100644 --- a/apps/client/src/widgets/type_widgets/Attachment.tsx +++ b/apps/client/src/widgets/type_widgets/Attachment.tsx @@ -239,6 +239,8 @@ function AttachmentActions({ attachment, copyAttachmentLinkToClipboard }: { atta text={} buttonClassName="icon-action-always-border" iconAction + dropdownContainerClassName="mobile-bottom-menu" + mobileBackdrop > {shouldDisplayNoChildrenWarning && ( - - - + <> + + + + )} - ) + ); } diff --git a/apps/client/src/widgets/type_widgets/ContentWidget.css b/apps/client/src/widgets/type_widgets/ContentWidget.css index fb1fb4574c..3d1e9c4b5b 100644 --- a/apps/client/src/widgets/type_widgets/ContentWidget.css +++ b/apps/client/src/widgets/type_widgets/ContentWidget.css @@ -1,16 +1,7 @@ -.type-contentWidget .note-detail { - height: 100%; -} - -.note-detail-content-widget { - height: 100%; -} - .note-detail-content-widget-content { padding: 15px; - height: 100%; } .note-detail.full-height .note-detail-content-widget-content { padding: 0; -} \ No newline at end of file +} diff --git a/apps/client/src/widgets/type_widgets/Empty.css b/apps/client/src/widgets/type_widgets/Empty.css index 9f04afbcf4..d48ed2b9e1 100644 --- a/apps/client/src/widgets/type_widgets/Empty.css +++ b/apps/client/src/widgets/type_widgets/Empty.css @@ -1,18 +1,20 @@ -.note-detail-empty { - container-type: size; - padding-top: 50px; - min-width: 350px; -} +body.desktop { + .note-detail-empty { + container-type: size; + padding-top: 50px; + min-width: 350px; + } -.note-detail-empty > * { - margin-inline: auto; - max-width: 850px; - padding-inline: 50px; -} - -@container (max-width: 600px) { .note-detail-empty > * { - padding-inline: 20px; + margin-inline: auto; + max-width: 850px; + padding-inline: 50px; + } + + @container (max-width: 600px) { + .note-detail-empty > * { + padding-inline: 20px; + } } } @@ -24,10 +26,22 @@ } .workspace-notes .workspace-note { - width: 130px; text-align: center; margin: 10px; border: 1px transparent solid; + + .workspace-icon { + text-align: center; + font-size: 250%; + } + + @media (min-width: 992px) { + width: 130px; + + .workspace-icon { + font-size: 500%; + } + } } .workspace-notes .workspace-note:hover { @@ -37,8 +51,6 @@ } .note-detail-empty-results .aa-dropdown-menu { - max-height: 50vh; - overflow: scroll; border: var(--bs-border-width) solid var(--bs-border-color); border-top: 0; } @@ -55,8 +67,3 @@ .empty-tab-search .input-clearer-button { border-bottom-right-radius: 0; } - -.workspace-icon { - text-align: center; - font-size: 500%; -} \ No newline at end of file diff --git a/apps/client/src/widgets/type_widgets/MindMap.tsx b/apps/client/src/widgets/type_widgets/MindMap.tsx index 8c6b36eb7a..4c2dde2e3c 100644 --- a/apps/client/src/widgets/type_widgets/MindMap.tsx +++ b/apps/client/src/widgets/type_widgets/MindMap.tsx @@ -34,6 +34,7 @@ const LOCALE_MAPPINGS: Record "en-GB": "en", es: "es", fr: "fr", + ga: null, it: "it", ja: "ja", pt: "pt", diff --git a/apps/client/src/widgets/type_widgets/ProtectedSession.css b/apps/client/src/widgets/type_widgets/ProtectedSession.css index 0ade6a39aa..6bfcb87737 100644 --- a/apps/client/src/widgets/type_widgets/ProtectedSession.css +++ b/apps/client/src/widgets/type_widgets/ProtectedSession.css @@ -1,9 +1,6 @@ .protected-session-password-component { - width: 300px; - margin: 30px auto auto; -} - -.protected-session-password-component input, -.protected-session-password-component button { - margin-top: 12px; + display: flex; + margin-inline: 40px; + flex-direction: column; + justify-content: center; } \ No newline at end of file diff --git a/apps/client/src/widgets/type_widgets/ProtectedSession.tsx b/apps/client/src/widgets/type_widgets/ProtectedSession.tsx index b7af4aebc6..a735f271e4 100644 --- a/apps/client/src/widgets/type_widgets/ProtectedSession.tsx +++ b/apps/client/src/widgets/type_widgets/ProtectedSession.tsx @@ -20,7 +20,9 @@ export default function ProtectedSession() { }, [ passwordRef ]); return ( -
+ + + ) -} +} \ No newline at end of file diff --git a/apps/client/src/widgets/type_widgets/Render.css b/apps/client/src/widgets/type_widgets/Render.css index 2595da0d84..7597b47cd2 100644 --- a/apps/client/src/widgets/type_widgets/Render.css +++ b/apps/client/src/widgets/type_widgets/Render.css @@ -1,8 +1,7 @@ .note-detail-render { position: relative; -} -.note-detail-render .note-detail-render-help { - margin: 50px; - padding: 20px; -} \ No newline at end of file + &>.admonition { + margin: 1em; + } +} diff --git a/apps/client/src/widgets/type_widgets/Render.tsx b/apps/client/src/widgets/type_widgets/Render.tsx index f47e58f2de..46c2e3a7a8 100644 --- a/apps/client/src/widgets/type_widgets/Render.tsx +++ b/apps/client/src/widgets/type_widgets/Render.tsx @@ -2,22 +2,59 @@ import "./Render.css"; import { useEffect, useRef, useState } from "preact/hooks"; +import FNote from "../../entities/fnote"; import attributes from "../../services/attributes"; import { t } from "../../services/i18n"; +import note_create from "../../services/note_create"; import render from "../../services/render"; -import Alert from "../react/Alert"; -import { useTriliumEvent } from "../react/hooks"; -import RawHtml from "../react/RawHtml"; +import toast from "../../services/toast"; +import { getErrorMessage } from "../../services/utils"; +import Admonition from "../react/Admonition"; +import Button, { SplitButton } from "../react/Button"; +import FormGroup from "../react/FormGroup"; +import { FormListItem } from "../react/FormList"; +import { useNoteRelation, useTriliumEvent } from "../react/hooks"; +import NoteAutocomplete from "../react/NoteAutocomplete"; import { refToJQuerySelector } from "../react/react_utils"; +import SetupForm from "./helpers/SetupForm"; import { TypeWidgetProps } from "./type_widget"; -export default function Render({ note, noteContext, ntxId }: TypeWidgetProps) { +const HELP_PAGE = "HcABDtFCkbFN"; + +const PREACT_SAMPLE = /*js*/`\ +export default function() { + return

Hello world.

; +} +`; + +const HTML_SAMPLE = /*html*/`\ +

Hello world.

+`; + +export default function Render(props: TypeWidgetProps) { + const { note } = props; + const [ renderNote ] = useNoteRelation(note, "renderNote"); + const [ disabledRenderNote ] = useNoteRelation(note, "disabled:renderNote"); + + if (disabledRenderNote) { + return ; + } + + if (!renderNote) { + return ; + } + + return ; +} + +function RenderContent({ note, noteContext, ntxId }: TypeWidgetProps) { const contentRef = useRef(null); - const [ renderNotesFound, setRenderNotesFound ] = useState(false); + const [ error, setError ] = useState(null); function refresh() { if (!contentRef) return; - render.render(note, refToJQuerySelector(contentRef)).then(setRenderNotesFound); + setError(null); + render.render(note, refToJQuerySelector(contentRef), setError); } useEffect(refresh, [ note ]); @@ -49,14 +86,72 @@ export default function Render({ note, noteContext, ntxId }: TypeWidgetProps) { return ( <> - {!renderNotesFound && ( - -

{t("render.note_detail_render_help_1")}

-

-
+ {error && ( + + {getErrorMessage(error)} + )} -
); } + +function DisabledRender({ note }: TypeWidgetProps) { + return ( + +

{t("render.disabled_description")}

+