mirror of
https://github.com/zadam/trilium.git
synced 2026-04-13 07:27:54 +02:00
Compare commits
24 Commits
renovate/a
...
feat/searc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bd25ae77fc | ||
|
|
9aec8be1c0 | ||
|
|
90ac727250 | ||
|
|
5bc9840825 | ||
|
|
48dd93b94b | ||
|
|
ac231374f6 | ||
|
|
87fc4e1281 | ||
|
|
8fd2cb39c1 | ||
|
|
24a01aefe2 | ||
|
|
06fb9c0a6b | ||
|
|
bc0942180e | ||
|
|
f358563c27 | ||
|
|
dcaebeea83 | ||
|
|
ac13af73c5 | ||
|
|
ba529d2721 | ||
|
|
f23a7b4842 | ||
|
|
5718631889 | ||
|
|
da3d71d21e | ||
|
|
b533546236 | ||
|
|
1c148f407c | ||
|
|
9403efa9a1 | ||
|
|
6a06fc7995 | ||
|
|
77733ce205 | ||
|
|
585b6ccd3e |
2
.github/actions/build-server/action.yml
vendored
2
.github/actions/build-server/action.yml
vendored
@@ -8,7 +8,7 @@ inputs:
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- uses: pnpm/action-setup@v5
|
||||
- uses: pnpm/action-setup@v4
|
||||
- name: Set up node & dependencies
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
|
||||
@@ -55,7 +55,7 @@ runs:
|
||||
# Post deployment URL as PR comment
|
||||
- name: Comment PR with Preview URL
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v9
|
||||
uses: actions/github-script@v8
|
||||
env:
|
||||
COMMENT_BODY: ${{ inputs.comment_body }}
|
||||
PRODUCTION_URL: ${{ inputs.production_url }}
|
||||
|
||||
2
.github/actions/report-size/action.yml
vendored
2
.github/actions/report-size/action.yml
vendored
@@ -69,7 +69,7 @@ runs:
|
||||
|
||||
# Post github action comment
|
||||
- name: Post comment
|
||||
uses: marocchino/sticky-pull-request-comment@v3
|
||||
uses: marocchino/sticky-pull-request-comment@v2
|
||||
if: ${{ steps.bundleSize.outputs.hasDifferences == 'true' }} # post only in case of changes
|
||||
with:
|
||||
number: ${{ github.event.pull_request.number }}
|
||||
|
||||
51
.github/copilot-instructions.md
vendored
51
.github/copilot-instructions.md
vendored
@@ -1,7 +1,5 @@
|
||||
# Trilium Notes - AI Coding Agent Instructions
|
||||
|
||||
> **Note**: When updating this file, also update `CLAUDE.md` in the repository root to keep both AI coding assistants in sync.
|
||||
|
||||
## Project Overview
|
||||
|
||||
Trilium Notes is a hierarchical note-taking application with advanced features like synchronization, scripting, and rich text editing. Built as a TypeScript monorepo using pnpm, it implements a three-layer caching architecture (Becca/Froca/Shaca) with a widget-based UI system and supports extensive user scripting capabilities.
|
||||
@@ -117,15 +115,6 @@ class MyNoteWidget extends NoteContextAwareWidget {
|
||||
|
||||
**Important**: Widgets use jQuery (`this.$widget`) for DOM manipulation. Don't mix React patterns here.
|
||||
|
||||
### Reusable Preact Components
|
||||
Common UI components are available in `apps/client/src/widgets/react/` — prefer reusing these over creating custom implementations:
|
||||
- `NoItems` - Empty state placeholder with icon and message (use for "no results", "too many items", error states)
|
||||
- `ActionButton` - Consistent button styling with icon support
|
||||
- `FormTextBox` - Text input with validation and controlled input handling
|
||||
- `Slider` - Range slider with label
|
||||
- `Checkbox`, `RadioButton` - Form controls
|
||||
- `CollapsibleSection` - Expandable content sections
|
||||
|
||||
## Development Workflow
|
||||
|
||||
### Running & Testing
|
||||
@@ -197,14 +186,6 @@ When adding query parameters to ETAPI endpoints (`apps/server/src/etapi/`), main
|
||||
|
||||
**Auth note**: ETAPI uses basic auth with tokens. Internal API endpoints trust the frontend.
|
||||
|
||||
### Adding New LLM Tools
|
||||
Tools are defined using `defineTools()` in `apps/server/src/services/llm/tools/` and automatically registered for both the LLM chat and MCP server.
|
||||
|
||||
1. Add the tool definition in the appropriate module (`note_tools.ts`, `attribute_tools.ts`, `hierarchy_tools.ts`) or create a new module
|
||||
2. Each tool needs: `description`, `inputSchema` (Zod), `execute` function, and optionally `mutates: true` for write operations or `needsContext: true` for tools that need the current note context
|
||||
3. If creating a new module, wrap tools in `defineTools({...})` and add the registry to `allToolRegistries` in `tools/index.ts`
|
||||
4. Add a client-side friendly name in `apps/client/src/translations/en/translation.json` under `llm.tools.<tool_name>` — use **imperative tense** (e.g. "Search notes", "Create note", "Get attributes"), not present continuous
|
||||
|
||||
### Database Migrations
|
||||
- Add scripts in `apps/server/src/migrations/YYMMDD_HHMM__description.sql`
|
||||
- Update schema in `apps/server/src/assets/db/schema.sql`
|
||||
@@ -232,12 +213,6 @@ Tools are defined using `defineTools()` in `apps/server/src/services/llm/tools/`
|
||||
|
||||
10. **Attribute inheritance can be complex** - When checking for labels/relations, use `note.getOwnedAttribute()` for direct attributes or `note.getAttribute()` for inherited ones. Don't assume attributes are directly on the note.
|
||||
|
||||
## MCP Server
|
||||
- Trilium exposes an MCP (Model Context Protocol) server at `http://localhost:8080/mcp`, configured in `.mcp.json`
|
||||
- The MCP server is **only available when the Trilium server is running** (`pnpm run server:start`)
|
||||
- It provides tools for reading, searching, and modifying notes directly from the AI assistant
|
||||
- Use it to interact with actual note data when developing or debugging note-related features
|
||||
|
||||
## TypeScript Configuration
|
||||
|
||||
- **Project references**: Monorepo uses TypeScript project references (`tsconfig.json`)
|
||||
@@ -300,12 +275,6 @@ View types are configured via `#viewType` label (e.g., `#viewType=table`). Each
|
||||
- Register in `packages/ckeditor5/src/plugins.ts`
|
||||
- See `ckeditor5-admonition`, `ckeditor5-footnotes`, `ckeditor5-math`, `ckeditor5-mermaid` for examples
|
||||
|
||||
### Updating PDF.js
|
||||
1. Update `pdfjs-dist` version in `packages/pdfjs-viewer/package.json`
|
||||
2. Run `npx tsx scripts/update-viewer.ts` from that directory
|
||||
3. Run `pnpm build` to verify success
|
||||
4. Commit all changes including updated viewer files
|
||||
|
||||
### Database Migrations
|
||||
- Add migration scripts in `apps/server/src/migrations/YYMMDD_HHMM__description.sql`
|
||||
- Update schema in `apps/server/src/assets/db/schema.sql`
|
||||
@@ -330,29 +299,9 @@ Trilium provides powerful user scripting capabilities:
|
||||
- Translation files in `apps/client/src/translations/`
|
||||
- Use translation system via `t()` function
|
||||
- Automatic pluralization: Add `_other` suffix to translation keys (e.g., `item` and `item_other` for singular/plural)
|
||||
- When a translated string contains **interpolated components** (e.g. links, note references) whose order may vary across languages, use `<Trans>` from `react-i18next` instead of `t()`. This lets translators reorder components freely (e.g. `"<Note/> in <Parent/>"` vs `"in <Parent/>, <Note/>"`)
|
||||
- When adding a new locale, follow the step-by-step guide in `docs/Developer Guide/Developer Guide/Concepts/Internationalisation Translations/Adding a new locale.md`
|
||||
|
||||
#### Client vs Server Translation Usage
|
||||
- **Client-side**: `import { t } from "../services/i18n"` with keys in `apps/client/src/translations/en/translation.json`
|
||||
- **Server-side**: `import { t } from "i18next"` with keys in `apps/server/src/assets/translations/en/server.json`
|
||||
- **Interpolation**: Use `{{variable}}` for normal interpolation; use `{{- variable}}` (with hyphen) for **unescaped** interpolation when the value contains special characters like quotes that shouldn't be HTML-escaped
|
||||
|
||||
### Storing User Preferences
|
||||
- **Do not use `localStorage`** for user preferences — Trilium has a synced options system that persists across devices
|
||||
- To add a new user preference:
|
||||
1. Add the option type to `OptionDefinitions` in `packages/commons/src/lib/options_interface.ts`
|
||||
2. Add a default value in `apps/server/src/services/options_init.ts` in the `defaultOptions` array
|
||||
3. **Whitelist the option** in `apps/server/src/routes/api/options.ts` by adding it to `ALLOWED_OPTIONS` (required for client updates)
|
||||
4. Use `useTriliumOption("optionName")` hook in React components to read/write the option
|
||||
- Available hooks: `useTriliumOption` (string), `useTriliumOptionBool`, `useTriliumOptionInt`, `useTriliumOptionJson`
|
||||
- See `docs/Developer Guide/Developer Guide/Concepts/Options/Creating a new option.md` for detailed documentation
|
||||
|
||||
## Testing Conventions
|
||||
|
||||
- **Write concise tests**: Group related assertions together in a single test case rather than creating many one-shot tests
|
||||
- **Extract and test business logic**: When adding pure business logic (e.g., data transformations, migrations, validations), extract it as a separate function and always write unit tests for it
|
||||
|
||||
```typescript
|
||||
// ETAPI test pattern
|
||||
describe("etapi/feature", () => {
|
||||
|
||||
2
.github/workflows/deploy-docs.yml
vendored
2
.github/workflows/deploy-docs.yml
vendored
@@ -45,7 +45,7 @@ jobs:
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v5
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
|
||||
18
.github/workflows/dev.yml
vendored
18
.github/workflows/dev.yml
vendored
@@ -1,13 +1,9 @@
|
||||
name: Dev
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- "release/*"
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- "release/*"
|
||||
branches: [ main ]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
@@ -30,7 +26,7 @@ jobs:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- uses: pnpm/action-setup@v5
|
||||
- uses: pnpm/action-setup@v4
|
||||
- name: Set up node & dependencies
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
@@ -78,7 +74,7 @@ jobs:
|
||||
- test_dev
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: pnpm/action-setup@v5
|
||||
- uses: pnpm/action-setup@v4
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
- name: Update build info
|
||||
@@ -93,7 +89,7 @@ jobs:
|
||||
key: ${{ secrets.RELATIVE_CI_CLIENT_KEY }}
|
||||
- name: Trigger server build
|
||||
run: pnpm run server:build
|
||||
- uses: docker/setup-buildx-action@v4
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
- uses: docker/build-push-action@v7
|
||||
with:
|
||||
context: apps/server
|
||||
@@ -113,7 +109,7 @@ jobs:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- uses: pnpm/action-setup@v5
|
||||
- uses: pnpm/action-setup@v4
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
@@ -128,7 +124,7 @@ jobs:
|
||||
run: echo "TEST_TAG=${TEST_TAG,,}" >> $GITHUB_ENV
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v4
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Build and export to Docker
|
||||
uses: docker/build-push-action@v7
|
||||
|
||||
2
.github/workflows/i18n.yml
vendored
2
.github/workflows/i18n.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: pnpm/action-setup@v5
|
||||
- uses: pnpm/action-setup@v4
|
||||
- name: Set up node & dependencies
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
|
||||
8
.github/workflows/main-docker.yml
vendored
8
.github/workflows/main-docker.yml
vendored
@@ -40,9 +40,9 @@ jobs:
|
||||
run: echo "TEST_TAG=${TEST_TAG,,}" >> $GITHUB_ENV
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v4
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- uses: pnpm/action-setup@v5
|
||||
- uses: pnpm/action-setup@v4
|
||||
- name: Set up node & dependencies
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
@@ -142,7 +142,7 @@ jobs:
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
- uses: pnpm/action-setup@v5
|
||||
- uses: pnpm/action-setup@v4
|
||||
- name: Set up node & dependencies
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
@@ -178,7 +178,7 @@ jobs:
|
||||
uses: docker/setup-qemu-action@v4
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v4
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to GHCR
|
||||
uses: docker/login-action@v4
|
||||
|
||||
8
.github/workflows/nightly.yml
vendored
8
.github/workflows/nightly.yml
vendored
@@ -61,7 +61,7 @@ jobs:
|
||||
runs-on: ${{ matrix.os.image }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: pnpm/action-setup@v5
|
||||
- uses: pnpm/action-setup@v4
|
||||
- name: Set up node & dependencies
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
@@ -69,8 +69,6 @@ jobs:
|
||||
cache: 'pnpm'
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
env:
|
||||
npm_config_package_import_method: copy
|
||||
- name: Update nightly version
|
||||
run: pnpm run chore:ci-update-nightly-version
|
||||
- name: Run the build
|
||||
@@ -93,7 +91,7 @@ jobs:
|
||||
GPG_SIGNING_KEY: ${{ secrets.GPG_SIGN_KEY }}
|
||||
|
||||
- name: Publish release
|
||||
uses: softprops/action-gh-release@v2.6.1
|
||||
uses: softprops/action-gh-release@v2.5.0
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
with:
|
||||
make_latest: false
|
||||
@@ -134,7 +132,7 @@ jobs:
|
||||
arch: ${{ matrix.arch }}
|
||||
|
||||
- name: Publish release
|
||||
uses: softprops/action-gh-release@v2.6.1
|
||||
uses: softprops/action-gh-release@v2.5.0
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
with:
|
||||
make_latest: false
|
||||
|
||||
2
.github/workflows/playwright.yml
vendored
2
.github/workflows/playwright.yml
vendored
@@ -38,7 +38,7 @@ jobs:
|
||||
filter: tree:0
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: pnpm/action-setup@v5
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 24
|
||||
|
||||
6
.github/workflows/release.yml
vendored
6
.github/workflows/release.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- uses: pnpm/action-setup@v5
|
||||
- uses: pnpm/action-setup@v4
|
||||
- name: Set up node & dependencies
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
@@ -66,7 +66,7 @@ jobs:
|
||||
runs-on: ${{ matrix.os.image }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: pnpm/action-setup@v5
|
||||
- uses: pnpm/action-setup@v4
|
||||
- name: Set up node & dependencies
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
@@ -150,7 +150,7 @@ jobs:
|
||||
path: upload
|
||||
|
||||
- name: Publish stable release
|
||||
uses: softprops/action-gh-release@v2.6.1
|
||||
uses: softprops/action-gh-release@v2.5.0
|
||||
with:
|
||||
draft: false
|
||||
body_path: docs/Release Notes/Release Notes/${{ github.ref_name }}.md
|
||||
|
||||
4
.github/workflows/web-clipper.yml
vendored
4
.github/workflows/web-clipper.yml
vendored
@@ -32,7 +32,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: pnpm/action-setup@v5
|
||||
- uses: pnpm/action-setup@v4
|
||||
- name: Set up node & dependencies
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
@@ -58,7 +58,7 @@ jobs:
|
||||
compression-level: 0
|
||||
|
||||
- name: Release web clipper extension
|
||||
uses: softprops/action-gh-release@v2.6.1
|
||||
uses: softprops/action-gh-release@v2.5.0
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/web-clipper-v') }}
|
||||
with:
|
||||
draft: false
|
||||
|
||||
2
.github/workflows/website.yml
vendored
2
.github/workflows/website.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: pnpm/action-setup@v5
|
||||
- uses: pnpm/action-setup@v4
|
||||
- name: Set up node & dependencies
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -46,6 +46,7 @@ upload
|
||||
|
||||
/.direnv
|
||||
/result
|
||||
.svelte-kit
|
||||
|
||||
# docs
|
||||
site/
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"mcpServers": {
|
||||
"trilium": {
|
||||
"type": "http",
|
||||
"url": "http://localhost:8080/mcp"
|
||||
}
|
||||
}
|
||||
}
|
||||
88
CLAUDE.md
88
CLAUDE.md
@@ -2,8 +2,6 @@
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
> **Note**: When updating this file, also update `.github/copilot-instructions.md` to keep both AI coding assistants in sync.
|
||||
|
||||
## Overview
|
||||
|
||||
Trilium Notes is a hierarchical note-taking application with advanced features like synchronization, scripting, and rich text editing. It's built as a TypeScript monorepo using pnpm, with multiple applications and shared packages.
|
||||
@@ -68,15 +66,6 @@ Frontend uses a widget system (`apps/client/src/widgets/`):
|
||||
- `RightPanelWidget` - Widgets displayed in the right panel
|
||||
- Type-specific widgets in `type_widgets/` directory
|
||||
|
||||
#### Reusable Preact Components
|
||||
Common UI components are available in `apps/client/src/widgets/react/` — prefer reusing these over creating custom implementations:
|
||||
- `NoItems` - Empty state placeholder with icon and message (use for "no results", "too many items", error states)
|
||||
- `ActionButton` - Consistent button styling with icon support
|
||||
- `FormTextBox` - Text input with validation and controlled input handling
|
||||
- `Slider` - Range slider with label
|
||||
- `Checkbox`, `RadioButton` - Form controls
|
||||
- `CollapsibleSection` - Expandable content sections
|
||||
|
||||
#### API Architecture
|
||||
- **Internal API**: REST endpoints in `apps/server/src/routes/api/`
|
||||
- **ETAPI**: External API for third-party integrations (`apps/server/src/etapi/`)
|
||||
@@ -119,8 +108,6 @@ Trilium supports multiple note types, each with specialized widgets:
|
||||
- Client tests can run in parallel
|
||||
- E2E tests use Playwright for both server and desktop apps
|
||||
- Build validation tests check artifact integrity
|
||||
- **Write concise tests**: Group related assertions together in a single test case rather than creating many one-shot tests
|
||||
- **Extract and test business logic**: When adding pure business logic (e.g., data transformations, migrations, validations), extract it as a separate function and always write unit tests for it
|
||||
|
||||
### Scripting System
|
||||
Trilium provides powerful user scripting capabilities:
|
||||
@@ -131,21 +118,6 @@ Trilium provides powerful user scripting capabilities:
|
||||
### Internationalization
|
||||
- Translation files in `apps/client/src/translations/`
|
||||
- Supported languages: English, German, Spanish, French, Romanian, Chinese
|
||||
- **Only add new translation keys to `en/translation.json`** — translations for other languages are managed via Weblate and will be contributed by the community
|
||||
- Third-party components (e.g., mind-map context menu) should use i18next `t()` for their labels, with the English strings added to `en/translation.json` under a dedicated namespace (e.g., `"mind-map"`)
|
||||
- When a translated string contains **interpolated components** (e.g. links, note references) whose order may vary across languages, use `<Trans>` from `react-i18next` instead of `t()`. This lets translators reorder components freely (e.g. `"<Note/> in <Parent/>"` vs `"in <Parent/>, <Note/>"`)
|
||||
- When adding a new locale, follow the step-by-step guide in `docs/Developer Guide/Developer Guide/Concepts/Internationalisation Translations/Adding a new locale.md`
|
||||
- **Server-side translations** (e.g. hidden subtree titles) go in `apps/server/src/assets/translations/en/server.json`, not in the client `translation.json`
|
||||
|
||||
#### Client vs Server Translation Usage
|
||||
- **Client-side**: `import { t } from "../services/i18n"` with keys in `apps/client/src/translations/en/translation.json`
|
||||
- **Server-side**: `import { t } from "i18next"` with keys in `apps/server/src/assets/translations/en/server.json`
|
||||
- **Interpolation**: Use `{{variable}}` for normal interpolation; use `{{- variable}}` (with hyphen) for **unescaped** interpolation when the value contains special characters like quotes that shouldn't be HTML-escaped
|
||||
|
||||
### Electron Desktop App
|
||||
- Desktop entry point: `apps/desktop/src/main.ts`, window management: `apps/server/src/services/window.ts`
|
||||
- IPC communication: use `electron.ipcMain.on(channel, handler)` on server side, `electron.ipcRenderer.send(channel, data)` on client side
|
||||
- Electron-only features should check `isElectron()` from `apps/client/src/services/utils.ts` (client) or `utils.isElectron` (server)
|
||||
|
||||
### Security Considerations
|
||||
- Per-note encryption with granular protected sessions
|
||||
@@ -153,25 +125,6 @@ Trilium provides powerful user scripting capabilities:
|
||||
- OpenID and TOTP authentication support
|
||||
- Sanitization of user-generated content
|
||||
|
||||
### Client-Side API Restrictions
|
||||
- **Do not use `crypto.randomUUID()`** or other Web Crypto APIs that require secure contexts - Trilium can run over HTTP, not just HTTPS
|
||||
- Use `randomString()` from `apps/client/src/services/utils.ts` for generating IDs instead
|
||||
|
||||
### Storing User Preferences
|
||||
- **Do not use `localStorage`** for user preferences — Trilium has a synced options system that persists across devices
|
||||
- To add a new user preference:
|
||||
1. Add the option type to `OptionDefinitions` in `packages/commons/src/lib/options_interface.ts`
|
||||
2. Add a default value in `apps/server/src/services/options_init.ts` in the `defaultOptions` array
|
||||
3. **Whitelist the option** in `apps/server/src/routes/api/options.ts` by adding it to `ALLOWED_OPTIONS` (required for client updates)
|
||||
4. Use `useTriliumOption("optionName")` hook in React components to read/write the option
|
||||
- Available hooks: `useTriliumOption` (string), `useTriliumOptionBool`, `useTriliumOptionInt`, `useTriliumOptionJson`
|
||||
- See `docs/Developer Guide/Developer Guide/Concepts/Options/Creating a new option.md` for detailed documentation
|
||||
|
||||
### Shared Types Policy
|
||||
- Types shared between client and server belong in `@triliumnext/commons` (`packages/commons/src/lib/`)
|
||||
- Import shared types directly from `@triliumnext/commons` - do not re-export them from app-specific modules
|
||||
- Keep app-specific types (e.g., `LlmProvider` for server, `StreamCallbacks` for client) in their respective apps
|
||||
|
||||
## Common Development Tasks
|
||||
|
||||
### Adding New Note Types
|
||||
@@ -187,51 +140,10 @@ Trilium provides powerful user scripting capabilities:
|
||||
- Create new package in `packages/` following existing plugin structure
|
||||
- Register in `packages/ckeditor5/src/plugins.ts`
|
||||
|
||||
### Adding Hidden System Notes
|
||||
The hidden subtree (`_hidden`) contains system notes with predictable IDs (prefixed with `_`). Defined in `apps/server/src/services/hidden_subtree.ts` via the `HiddenSubtreeItem` interface from `@triliumnext/commons`.
|
||||
|
||||
1. Add the note definition to `buildHiddenSubtreeDefinition()` in `apps/server/src/services/hidden_subtree.ts`
|
||||
2. Add a translation key for the title in `apps/server/src/assets/translations/en/server.json` under `"hidden-subtree"`
|
||||
3. The note is auto-created on startup by `checkHiddenSubtree()` — uses deterministic IDs so all sync cluster instances generate the same structure
|
||||
4. Key properties: `id` (must start with `_`), `title`, `type`, `icon` (format: `bx-icon-name` without `bx ` prefix), `attributes`, `children`, `content`
|
||||
5. Use `enforceAttributes: true` to keep attributes in sync, `enforceBranches: true` for correct placement, `enforceDeleted: true` to remove deprecated notes
|
||||
6. For launcher bar entries, see `hidden_subtree_launcherbar.ts`; for templates, see `hidden_subtree_templates.ts`
|
||||
|
||||
### Writing to Notes from Server Services
|
||||
- `note.setContent()` requires a CLS (Continuation Local Storage) context — wrap calls in `cls.init(() => { ... })` (from `apps/server/src/services/cls.ts`)
|
||||
- Operations called from Express routes already have CLS context; standalone services (schedulers, Electron IPC handlers) do not
|
||||
|
||||
### Adding New LLM Tools
|
||||
Tools are defined using `defineTools()` in `apps/server/src/services/llm/tools/` and automatically registered for both the LLM chat and MCP server.
|
||||
|
||||
1. Add the tool definition in the appropriate module (`note_tools.ts`, `attribute_tools.ts`, `attachment_tools.ts`, `hierarchy_tools.ts`) or create a new module
|
||||
2. Each tool needs: `description`, `inputSchema` (Zod), `execute` function, and optionally `mutates: true` for write operations
|
||||
3. If creating a new module, wrap tools in `defineTools({...})` and add the registry to `allToolRegistries` in `tools/index.ts`
|
||||
4. Add a client-side friendly name in `apps/client/src/translations/en/translation.json` under `llm.tools.<tool_name>` — use **imperative tense** (e.g. "Search notes", "Create note", "Get attributes"), not present continuous
|
||||
5. Use ETAPI (`apps/server/src/etapi/`) as inspiration for what fields to expose, but **do not import ETAPI mappers** — inline the field mappings directly in the tool so the LLM layer stays decoupled from the API layer
|
||||
|
||||
### Updating PDF.js
|
||||
1. Update `pdfjs-dist` version in `packages/pdfjs-viewer/package.json`
|
||||
2. Run `npx tsx scripts/update-viewer.ts` from that directory
|
||||
3. Run `pnpm build` to verify success
|
||||
4. Commit all changes including updated viewer files
|
||||
|
||||
### Database Migrations
|
||||
- Add migration scripts in `apps/server/src/migrations/`
|
||||
- Update schema in `apps/server/src/assets/db/schema.sql`
|
||||
|
||||
### Server-Side Static Assets
|
||||
- Static assets (templates, SQL, translations, etc.) go in `apps/server/src/assets/`
|
||||
- Access them at runtime via `RESOURCE_DIR` from `apps/server/src/services/resource_dir.ts` (e.g. `path.join(RESOURCE_DIR, "llm", "skills", "file.md")`)
|
||||
- **Do not use `import.meta.url`/`fileURLToPath`** to resolve file paths — the server is bundled into CJS for production, so `import.meta.url` will not point to the source directory
|
||||
- **Do not use `__dirname` with relative paths** from source files — after bundling, `__dirname` points to the bundle output, not the original source tree
|
||||
|
||||
## MCP Server
|
||||
- Trilium exposes an MCP (Model Context Protocol) server at `http://localhost:8080/mcp`, configured in `.mcp.json`
|
||||
- The MCP server is **only available when the Trilium server is running** (`pnpm run server:start`)
|
||||
- It provides tools for reading, searching, and modifying notes directly from the AI assistant
|
||||
- Use it to interact with actual note data when developing or debugging note-related features
|
||||
|
||||
## Build System Notes
|
||||
- Uses pnpm for monorepo management
|
||||
- Vite for fast development builds
|
||||
|
||||
84
SECURITY.md
84
SECURITY.md
@@ -2,87 +2,13 @@
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Only the latest stable minor release receives security fixes.
|
||||
In the (still active) 0.X phase of the project only the latest stable minor release is getting bugfixes (including security ones).
|
||||
|
||||
For example, if the latest stable version is 0.92.3 and the latest beta is 0.93.0-beta, then only the 0.92.x line will receive security patches. Older versions (like 0.91.x) will not receive fixes.
|
||||
So e.g. if the latest stable version is 0.42.3 and the latest beta version is 0.43.0-beta, then 0.42 line will still get security fixes but older versions (like 0.41.X) won't get any fixes.
|
||||
|
||||
This policy may be altered on a case-by-case basis for critical vulnerabilities.
|
||||
Description above is a general rule and may be altered on case by case basis.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
**Please report all security vulnerabilities through [GitHub Security Advisories](https://github.com/TriliumNext/Notes/security/advisories/new).**
|
||||
|
||||
We do not accept security reports via email, public issues, or other channels. GitHub Security Advisories allows us to:
|
||||
- Discuss and triage vulnerabilities privately
|
||||
- Coordinate fixes before public disclosure
|
||||
- Credit reporters appropriately
|
||||
- Publish advisories with CVE identifiers
|
||||
|
||||
### What to Include
|
||||
|
||||
When reporting, please provide:
|
||||
- A clear description of the vulnerability
|
||||
- Steps to reproduce or proof-of-concept
|
||||
- Affected versions (if known)
|
||||
- Potential impact assessment
|
||||
- Any suggested mitigations or fixes
|
||||
|
||||
### Response Timeline
|
||||
|
||||
- **Initial response**: Within 7 days
|
||||
- **Triage decision**: Within 14 days
|
||||
- **Fix timeline**: Depends on severity and complexity
|
||||
|
||||
## Scope
|
||||
|
||||
### In Scope
|
||||
|
||||
- Remote code execution
|
||||
- Authentication/authorization bypass
|
||||
- Cross-site scripting (XSS) that affects other users
|
||||
- SQL injection
|
||||
- Path traversal
|
||||
- Sensitive data exposure
|
||||
- Privilege escalation
|
||||
|
||||
### Out of Scope (Won't Fix)
|
||||
|
||||
The following are considered out of scope or accepted risks:
|
||||
|
||||
#### Self-XSS / Self-Injection
|
||||
Trilium is a personal knowledge base where users have full control over their own data. Users can intentionally create notes containing scripts, HTML, or other executable content. This is by design - Trilium's scripting system allows users to extend functionality with custom JavaScript.
|
||||
|
||||
Vulnerabilities that require a user to inject malicious content into their own notes and then view it themselves are not considered security issues.
|
||||
|
||||
#### Electron Architecture (nodeIntegration)
|
||||
Trilium's desktop application runs with `nodeIntegration: true` to enable its powerful scripting features. This is an intentional design decision, similar to VS Code extensions having full system access. We mitigate risks by:
|
||||
- Sanitizing content at input boundaries
|
||||
- Fixing specific XSS vectors as they're discovered
|
||||
- Using Electron fuses to prevent external abuse
|
||||
|
||||
#### Authenticated User Actions
|
||||
Actions that require valid authentication and only affect the authenticated user's own data are generally not vulnerabilities.
|
||||
|
||||
#### Denial of Service via Resource Exhaustion
|
||||
Creating extremely large notes or performing many operations is expected user behavior in a note-taking application.
|
||||
|
||||
#### Missing Security Headers on Non-Sensitive Endpoints
|
||||
We implement security headers where they provide meaningful protection, but may omit them on endpoints where they provide no practical benefit.
|
||||
|
||||
## Coordinated Disclosure
|
||||
|
||||
We follow a coordinated disclosure process:
|
||||
|
||||
1. **Report received** - We acknowledge receipt and begin triage
|
||||
2. **Fix developed** - We develop and test a fix privately
|
||||
3. **Release prepared** - Security release is prepared with vague changelog
|
||||
4. **Users notified** - Release is published, users encouraged to upgrade
|
||||
5. **Advisory published** - After reasonable upgrade window (typically 2-4 weeks), full advisory is published
|
||||
|
||||
We appreciate reporters allowing us time to fix issues before public disclosure. We aim to credit all reporters in published advisories unless they prefer to remain anonymous.
|
||||
|
||||
## Security Updates
|
||||
|
||||
Security fixes are released as patch versions (e.g., 0.92.1 → 0.92.2) to minimize upgrade friction. We recommend all users keep their installations up to date.
|
||||
|
||||
Subscribe to GitHub releases or watch the repository to receive notifications of new releases.
|
||||
* For low severity vulnerabilities, they can be reported as GitHub issues.
|
||||
* For severe vulnerabilities, please report it using [GitHub Security Advisories](https://github.com/TriliumNext/Trilium/security/advisories).
|
||||
|
||||
@@ -14,13 +14,15 @@
|
||||
"keywords": [],
|
||||
"author": "Elian Doran <contact@eliandoran.me>",
|
||||
"license": "AGPL-3.0-only",
|
||||
"packageManager": "pnpm@10.33.0",
|
||||
"packageManager": "pnpm@10.32.0",
|
||||
"devDependencies": {
|
||||
"@redocly/cli": "2.26.0",
|
||||
"@redocly/cli": "2.20.2",
|
||||
"archiver": "7.0.1",
|
||||
"fs-extra": "11.3.4",
|
||||
"js-yaml": "4.1.1",
|
||||
"typedoc": "0.28.18",
|
||||
"typedoc-plugin-missing-exports": "4.1.3"
|
||||
"react": "19.2.4",
|
||||
"react-dom": "19.2.4",
|
||||
"typedoc": "0.28.17",
|
||||
"typedoc-plugin-missing-exports": "4.1.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@triliumnext/client",
|
||||
"version": "0.102.2",
|
||||
"version": "0.102.1",
|
||||
"description": "JQuery-based client for TriliumNext, used for both web and desktop (via Electron)",
|
||||
"private": true,
|
||||
"license": "AGPL-3.0-only",
|
||||
@@ -27,48 +27,51 @@
|
||||
"@maplibre/maplibre-gl-leaflet": "0.1.3",
|
||||
"@mermaid-js/layout-elk": "0.2.1",
|
||||
"@mind-elixir/node-menu": "5.0.1",
|
||||
"@preact/signals": "2.9.0",
|
||||
"@popperjs/core": "2.11.8",
|
||||
"@preact/signals": "2.8.2",
|
||||
"@triliumnext/ckeditor5": "workspace:*",
|
||||
"@triliumnext/codemirror": "workspace:*",
|
||||
"@triliumnext/commons": "workspace:*",
|
||||
"@triliumnext/highlightjs": "workspace:*",
|
||||
"@triliumnext/share-theme": "workspace:*",
|
||||
"@triliumnext/split.js": "workspace:*",
|
||||
"@univerjs/preset-sheets-conditional-formatting": "0.20.0",
|
||||
"@univerjs/preset-sheets-core": "0.20.0",
|
||||
"@univerjs/preset-sheets-data-validation": "0.20.0",
|
||||
"@univerjs/preset-sheets-filter": "0.20.0",
|
||||
"@univerjs/preset-sheets-find-replace": "0.20.0",
|
||||
"@univerjs/preset-sheets-note": "0.20.0",
|
||||
"@univerjs/preset-sheets-sort": "0.20.0",
|
||||
"@univerjs/presets": "0.20.0",
|
||||
"@zumer/snapdom": "2.8.0",
|
||||
"@univerjs/preset-sheets-conditional-formatting": "0.16.1",
|
||||
"@univerjs/preset-sheets-core": "0.16.1",
|
||||
"@univerjs/preset-sheets-data-validation": "0.16.1",
|
||||
"@univerjs/preset-sheets-filter": "0.16.1",
|
||||
"@univerjs/preset-sheets-find-replace": "0.16.1",
|
||||
"@univerjs/preset-sheets-note": "0.16.1",
|
||||
"@univerjs/preset-sheets-sort": "0.16.1",
|
||||
"@univerjs/presets": "0.16.1",
|
||||
"@zumer/snapdom": "2.1.0",
|
||||
"autocomplete.js": "0.38.1",
|
||||
"bootstrap": "5.3.8",
|
||||
"boxicons": "2.1.4",
|
||||
"clsx": "2.1.1",
|
||||
"color": "5.0.3",
|
||||
"debounce": "3.0.0",
|
||||
"dompurify": "3.3.3",
|
||||
"draggabilly": "3.0.0",
|
||||
"force-graph": "1.51.2",
|
||||
"i18next": "26.0.4",
|
||||
"i18next-http-backend": "3.0.4",
|
||||
"force-graph": "1.51.1",
|
||||
"globals": "17.4.0",
|
||||
"i18next": "25.8.17",
|
||||
"i18next-http-backend": "3.0.2",
|
||||
"jquery": "4.0.0",
|
||||
"jquery.fancytree": "2.38.5",
|
||||
"jsplumb": "2.15.6",
|
||||
"katex": "0.16.45",
|
||||
"katex": "0.16.38",
|
||||
"knockout": "3.5.1",
|
||||
"leaflet": "1.9.4",
|
||||
"leaflet-gpx": "2.2.0",
|
||||
"mark.js": "8.11.1",
|
||||
"marked": "18.0.0",
|
||||
"mermaid": "11.14.0",
|
||||
"mind-elixir": "5.10.0",
|
||||
"panzoom": "9.4.4",
|
||||
"preact": "10.29.1",
|
||||
"react-i18next": "17.0.2",
|
||||
"marked": "17.0.4",
|
||||
"mermaid": "11.12.3",
|
||||
"mind-elixir": "5.9.3",
|
||||
"normalize.css": "8.0.1",
|
||||
"panzoom": "9.4.3",
|
||||
"preact": "10.29.0",
|
||||
"react-i18next": "16.5.6",
|
||||
"react-window": "2.2.7",
|
||||
"reveal.js": "6.0.0",
|
||||
"reveal.js": "5.2.1",
|
||||
"rrule": "2.8.1",
|
||||
"svg-pan-zoom": "3.6.2",
|
||||
"tabulator-tables": "6.4.0",
|
||||
@@ -76,17 +79,18 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ckeditor/ckeditor5-inspector": "5.0.0",
|
||||
"@prefresh/vite": "3.0.0",
|
||||
"@prefresh/vite": "2.4.12",
|
||||
"@types/bootstrap": "5.2.10",
|
||||
"@types/jquery": "4.0.0",
|
||||
"@types/leaflet": "1.9.21",
|
||||
"@types/leaflet-gpx": "1.3.8",
|
||||
"@types/mark.js": "8.11.12",
|
||||
"@types/reveal.js": "5.2.2",
|
||||
"@types/tabulator-tables": "6.3.1",
|
||||
"copy-webpack-plugin": "14.0.0",
|
||||
"happy-dom": "20.8.9",
|
||||
"happy-dom": "20.8.3",
|
||||
"lightningcss": "1.32.0",
|
||||
"script-loader": "0.7.2",
|
||||
"vite-plugin-static-copy": "4.0.1"
|
||||
"vite-plugin-static-copy": "3.2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,10 @@
|
||||
import type { CKTextEditor } from "@triliumnext/ckeditor5";
|
||||
import type CodeMirror from "@triliumnext/codemirror";
|
||||
import { type LOCALE_IDS, SqlExecuteResponse } from "@triliumnext/commons";
|
||||
import { SqlExecuteResponse } from "@triliumnext/commons";
|
||||
import type { NativeImage, TouchBar } from "electron";
|
||||
import { ColumnComponent } from "tabulator-tables";
|
||||
|
||||
import type { Attribute } from "../services/attribute_parser.js";
|
||||
import bundleService from "../services/bundle.js";
|
||||
import froca from "../services/froca.js";
|
||||
import { initLocale, t } from "../services/i18n.js";
|
||||
import keyboardActionsService from "../services/keyboard_actions.js";
|
||||
@@ -303,7 +302,6 @@ export type CommandMappings = {
|
||||
ninthTab: CommandData;
|
||||
lastTab: CommandData;
|
||||
showNoteSource: CommandData;
|
||||
showNoteOCRText: CommandData;
|
||||
showSQLConsole: CommandData;
|
||||
showBackendLog: CommandData;
|
||||
showCheatsheet: CommandData;
|
||||
@@ -510,7 +508,7 @@ type EventMappings = {
|
||||
contentSafeMarginChanged: {
|
||||
top: number;
|
||||
noteContext: NoteContext;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
export type EventListener<T extends EventNames> = {
|
||||
@@ -564,7 +562,7 @@ export class AppContext extends Component {
|
||||
*/
|
||||
async earlyInit() {
|
||||
await options.initializedPromise;
|
||||
await initLocale((options.get("locale") || "en") as LOCALE_IDS);
|
||||
await initLocale();
|
||||
}
|
||||
|
||||
setLayout(layout: Layout) {
|
||||
@@ -579,6 +577,7 @@ export class AppContext extends Component {
|
||||
|
||||
this.tabManager.loadTabs();
|
||||
|
||||
const bundleService = (await import("../services/bundle.js")).default;
|
||||
setTimeout(() => bundleService.executeStartupBundles(), 2000);
|
||||
}
|
||||
|
||||
|
||||
@@ -148,19 +148,6 @@ export default class RootCommandExecutor extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
async showNoteOCRTextCommand() {
|
||||
const notePath = appContext.tabManager.getActiveContextNotePath();
|
||||
|
||||
if (notePath) {
|
||||
await appContext.tabManager.openTabWithNoteWithHoisting(notePath, {
|
||||
activate: true,
|
||||
viewScope: {
|
||||
viewMode: "ocr"
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async showAttachmentsCommand() {
|
||||
const notePath = appContext.tabManager.getActiveContextNotePath();
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ function initOnElectron() {
|
||||
const currentWindow = electronRemote.getCurrentWindow();
|
||||
const style = window.getComputedStyle(document.body);
|
||||
|
||||
initDarkOrLightMode();
|
||||
initDarkOrLightMode(style);
|
||||
initTransparencyEffects(style, currentWindow);
|
||||
initFullScreenDetection(currentWindow);
|
||||
|
||||
@@ -119,11 +119,11 @@ function initTransparencyEffects(style: CSSStyleDeclaration, currentWindow: Elec
|
||||
*
|
||||
* @param style the root CSS element to read variables from.
|
||||
*/
|
||||
function initDarkOrLightMode() {
|
||||
function initDarkOrLightMode(style: CSSStyleDeclaration) {
|
||||
let themeSource: typeof nativeTheme.themeSource = "system";
|
||||
|
||||
const themeStyle = window.glob.getThemeStyle();
|
||||
if (themeStyle !== "auto") {
|
||||
const themeStyle = style.getPropertyValue("--theme-style");
|
||||
if (style.getPropertyValue("--theme-style-auto") !== "true" && (themeStyle === "light" || themeStyle === "dark")) {
|
||||
themeSource = themeStyle;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { getNoteIcon } from "@triliumnext/commons";
|
||||
|
||||
import bundleService from "../services/bundle.js";
|
||||
import cssClassManager from "../services/css_class_manager.js";
|
||||
import type { Froca } from "../services/froca-interface.js";
|
||||
import noteAttributeCache from "../services/note_attribute_cache.js";
|
||||
@@ -19,7 +18,7 @@ const RELATION = "relation";
|
||||
* end user. Those types should be used only for checking against, they are
|
||||
* not for direct use.
|
||||
*/
|
||||
export type NoteType = "file" | "image" | "search" | "noteMap" | "launcher" | "doc" | "contentWidget" | "text" | "relationMap" | "render" | "canvas" | "mermaid" | "book" | "webView" | "code" | "mindMap" | "spreadsheet" | "llmChat";
|
||||
export type NoteType = "file" | "image" | "search" | "noteMap" | "launcher" | "doc" | "contentWidget" | "text" | "relationMap" | "render" | "canvas" | "mermaid" | "book" | "webView" | "code" | "mindMap" | "spreadsheet";
|
||||
|
||||
export interface NotePathRecord {
|
||||
isArchived: boolean;
|
||||
@@ -236,16 +235,6 @@ export default class FNote {
|
||||
return this.hasAttribute("label", "archived");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the note's metadata (title, icon) should not be editable.
|
||||
* This applies to system notes like options, help, and launch bar configuration.
|
||||
*/
|
||||
get isMetadataReadOnly() {
|
||||
return utils.isLaunchBarConfig(this.noteId)
|
||||
|| this.noteId.startsWith("_help_")
|
||||
|| this.noteId.startsWith("_options");
|
||||
}
|
||||
|
||||
getChildNoteIds() {
|
||||
return this.children;
|
||||
}
|
||||
@@ -1025,6 +1014,7 @@ export default class FNote {
|
||||
const env = this.getScriptEnv();
|
||||
|
||||
if (env === "frontend") {
|
||||
const bundleService = (await import("../services/bundle.js")).default;
|
||||
return await bundleService.getAndExecuteBundle(this.noteId);
|
||||
} else if (env === "backend") {
|
||||
await server.post(`script/run/${this.noteId}`);
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { getThemeStyle } from "./services/theme";
|
||||
|
||||
async function bootstrap() {
|
||||
showSplash();
|
||||
await setupGlob();
|
||||
@@ -40,7 +38,6 @@ async function setupGlob() {
|
||||
...json,
|
||||
activeDialog: null
|
||||
};
|
||||
window.glob.getThemeStyle = getThemeStyle;
|
||||
}
|
||||
|
||||
async function loadBootstrapCss() {
|
||||
@@ -52,65 +49,31 @@ async function loadBootstrapCss() {
|
||||
}
|
||||
}
|
||||
|
||||
type StylesheetRef = {
|
||||
href: string;
|
||||
media?: string;
|
||||
};
|
||||
|
||||
function getConfiguredThemeStylesheets(stylesheetsPath: string, theme: string, customThemeCssUrl?: string) {
|
||||
if (theme === "auto") {
|
||||
return [{ href: `${stylesheetsPath}/theme-dark.css`, media: "(prefers-color-scheme: dark)" }];
|
||||
}
|
||||
|
||||
if (theme === "dark") {
|
||||
return [{ href: `${stylesheetsPath}/theme-dark.css` }];
|
||||
}
|
||||
|
||||
if (theme === "next") {
|
||||
return [
|
||||
{ href: `${stylesheetsPath}/theme-next-light.css` },
|
||||
{ href: `${stylesheetsPath}/theme-next-dark.css`, media: "(prefers-color-scheme: dark)" }
|
||||
];
|
||||
}
|
||||
|
||||
if (theme === "next-light") {
|
||||
return [{ href: `${stylesheetsPath}/theme-next-light.css` }];
|
||||
}
|
||||
|
||||
if (theme === "next-dark") {
|
||||
return [{ href: `${stylesheetsPath}/theme-next-dark.css` }];
|
||||
}
|
||||
|
||||
if (theme !== "light" && customThemeCssUrl) {
|
||||
return [{ href: customThemeCssUrl }];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
function loadStylesheets() {
|
||||
const { device, assetPath, theme, themeBase, customThemeCssUrl } = window.glob;
|
||||
const stylesheetsPath = `${assetPath}/stylesheets`;
|
||||
const { device, assetPath, themeCssUrl, themeUseNextAsBase } = window.glob;
|
||||
|
||||
const cssToLoad: StylesheetRef[] = [];
|
||||
const cssToLoad: string[] = [];
|
||||
if (device !== "print") {
|
||||
cssToLoad.push({ href: `${stylesheetsPath}/ckeditor-theme.css` });
|
||||
cssToLoad.push({ href: `api/fonts` });
|
||||
cssToLoad.push({ href: `${stylesheetsPath}/theme-light.css` });
|
||||
cssToLoad.push(...getConfiguredThemeStylesheets(stylesheetsPath, theme, customThemeCssUrl));
|
||||
if (themeBase) {
|
||||
cssToLoad.push(...getConfiguredThemeStylesheets(stylesheetsPath, themeBase));
|
||||
cssToLoad.push(`${assetPath}/stylesheets/ckeditor-theme.css`);
|
||||
cssToLoad.push(`api/fonts`);
|
||||
cssToLoad.push(`${assetPath}/stylesheets/theme-light.css`);
|
||||
if (themeCssUrl) {
|
||||
cssToLoad.push(themeCssUrl);
|
||||
}
|
||||
cssToLoad.push({ href: `${stylesheetsPath}/style.css` });
|
||||
if (themeUseNextAsBase === "next") {
|
||||
cssToLoad.push(`${assetPath}/stylesheets/theme-next.css`);
|
||||
} else if (themeUseNextAsBase === "next-dark") {
|
||||
cssToLoad.push(`${assetPath}/stylesheets/theme-next-dark.css`);
|
||||
} else if (themeUseNextAsBase === "next-light") {
|
||||
cssToLoad.push(`${assetPath}/stylesheets/theme-next-light.css`);
|
||||
}
|
||||
cssToLoad.push(`${assetPath}/stylesheets/style.css`);
|
||||
}
|
||||
|
||||
for (const { href, media } of cssToLoad) {
|
||||
for (const href of cssToLoad) {
|
||||
const linkEl = document.createElement("link");
|
||||
linkEl.href = href;
|
||||
linkEl.rel = "stylesheet";
|
||||
if (media) {
|
||||
linkEl.media = media;
|
||||
}
|
||||
document.head.appendChild(linkEl);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import type { BrowserWindow } from "electron";
|
||||
|
||||
import type { CommandNames } from "../components/app_context.js";
|
||||
import appContext from "../components/app_context.js";
|
||||
import zoomService from "../components/zoom.js";
|
||||
import * as clipboardExt from "../services/clipboard_ext.js";
|
||||
import { t } from "../services/i18n.js";
|
||||
import options from "../services/options.js";
|
||||
import server from "../services/server.js";
|
||||
import utils from "../services/utils.js";
|
||||
import options from "../services/options.js";
|
||||
import zoomService from "../components/zoom.js";
|
||||
import contextMenu, { type MenuItem } from "./context_menu.js";
|
||||
import { t } from "../services/i18n.js";
|
||||
import server from "../services/server.js";
|
||||
import * as clipboardExt from "../services/clipboard_ext.js";
|
||||
import type { BrowserWindow } from "electron";
|
||||
import type { CommandNames, AppContext } from "../components/app_context.js";
|
||||
|
||||
function setupContextMenu() {
|
||||
const electron = utils.dynamicRequire("electron");
|
||||
@@ -17,6 +15,8 @@ function setupContextMenu() {
|
||||
// FIXME: Remove typecast once Electron is properly integrated.
|
||||
const { webContents } = remote.getCurrentWindow() as BrowserWindow;
|
||||
|
||||
let appContext: AppContext;
|
||||
|
||||
webContents.on("context-menu", (event, params) => {
|
||||
const { editFlags } = params;
|
||||
const hasText = params.selectionText.trim().length > 0;
|
||||
@@ -38,7 +38,7 @@ function setupContextMenu() {
|
||||
items.push({
|
||||
title: t("electron_context_menu.add-term-to-dictionary", { term: params.misspelledWord }),
|
||||
uiIcon: "bx bx-plus",
|
||||
handler: () => electron.ipcRenderer.send("add-word-to-dictionary", params.misspelledWord)
|
||||
handler: () => webContents.session.addWordToSpellCheckerDictionary(params.misspelledWord)
|
||||
});
|
||||
|
||||
items.push({ kind: "separator" });
|
||||
@@ -141,7 +141,7 @@ function setupContextMenu() {
|
||||
}
|
||||
|
||||
// Replace the placeholder with the real search keyword.
|
||||
const searchUrl = searchEngineUrl.replace("{keyword}", encodeURIComponent(params.selectionText));
|
||||
let searchUrl = searchEngineUrl.replace("{keyword}", encodeURIComponent(params.selectionText));
|
||||
|
||||
items.push({ kind: "separator" });
|
||||
|
||||
@@ -155,6 +155,10 @@ function setupContextMenu() {
|
||||
title: t("electron_context_menu.search_in_trilium", { term: shortenedSelection }),
|
||||
uiIcon: "bx bx-search",
|
||||
handler: async () => {
|
||||
if (!appContext) {
|
||||
appContext = (await import("../components/app_context.js")).default;
|
||||
}
|
||||
|
||||
await appContext.triggerCommand("searchNotes", {
|
||||
searchString: params.selectionText
|
||||
});
|
||||
|
||||
@@ -4,7 +4,6 @@ import { useCallback, useLayoutEffect, useRef } from "preact/hooks";
|
||||
import FNote from "./entities/fnote";
|
||||
import content_renderer from "./services/content_renderer";
|
||||
import { applyInlineMermaid } from "./services/content_renderer_text";
|
||||
import froca from "./services/froca";
|
||||
import { dynamicRequire, isElectron } from "./services/utils";
|
||||
import { CustomNoteList, useNoteViewType } from "./widgets/collections/NoteList";
|
||||
|
||||
@@ -31,6 +30,7 @@ async function main() {
|
||||
if (!noteId) return;
|
||||
|
||||
await import("./print.css");
|
||||
const froca = (await import("./services/froca")).default;
|
||||
const note = await froca.getNote(noteId);
|
||||
|
||||
const bodyWrapper = document.createElement("div");
|
||||
|
||||
@@ -6,8 +6,10 @@ import froca from "./froca";
|
||||
import server from "./server.js";
|
||||
|
||||
// Spy on server methods to track calls
|
||||
server.put = vi.fn(async () => ({})) as typeof server.put;
|
||||
server.remove = vi.fn(async () => ({})) as typeof server.remove;
|
||||
// @ts-expect-error the generic typing is causing issues here
|
||||
server.put = vi.fn(async <T> (url: string, data?: T) => ({} as T));
|
||||
// @ts-expect-error the generic typing is causing issues here
|
||||
server.remove = vi.fn(async <T> (url: string) => ({} as T));
|
||||
|
||||
describe("Set boolean with inheritance", () => {
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -120,7 +120,7 @@ async function deleteNotes(branchIdsToDelete: string[], forceDeleteAllClones = f
|
||||
|
||||
if (moveToParent) {
|
||||
try {
|
||||
await activateParentNotePath(branchIdsToDelete);
|
||||
await activateParentNotePath();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
@@ -152,28 +152,13 @@ async function deleteNotes(branchIdsToDelete: string[], forceDeleteAllClones = f
|
||||
return true;
|
||||
}
|
||||
|
||||
async function activateParentNotePath(branchIdsToDelete: string[]) {
|
||||
async function activateParentNotePath() {
|
||||
// this is not perfect, maybe we should find the next/previous sibling, but that's more complex
|
||||
const activeContext = appContext.tabManager.getActiveContext();
|
||||
const activeNotePath = activeContext?.notePathArray ?? [];
|
||||
const parentNotePathArr = activeContext?.notePathArray.slice(0, -1);
|
||||
|
||||
// Find the deleted branch that appears earliest in the active note's path
|
||||
let earliestIndex = activeNotePath.length;
|
||||
for (const branchId of branchIdsToDelete) {
|
||||
const branch = froca.getBranch(branchId);
|
||||
if (branch) {
|
||||
const index = activeNotePath.indexOf(branch.noteId);
|
||||
if (index !== -1 && index < earliestIndex) {
|
||||
earliestIndex = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Navigate to the parent of the highest deleted ancestor
|
||||
if (earliestIndex < activeNotePath.length) {
|
||||
const parentPath = activeNotePath.slice(0, earliestIndex);
|
||||
if (parentPath.length > 0) {
|
||||
await activeContext?.setNote(parentPath.join("/"));
|
||||
}
|
||||
if (parentNotePathArr && parentNotePathArr.length > 0) {
|
||||
activeContext?.setNote(parentNotePathArr.join("/"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ type WithNoteId<T> = T & {
|
||||
};
|
||||
export type Widget = WithNoteId<(LegacyWidget | WidgetDefinitionWithType)>;
|
||||
|
||||
async function getAndExecuteBundle(noteId: string, originEntity: Entity | null = null, script: string | null = null, params: string | null = null) {
|
||||
async function getAndExecuteBundle(noteId: string, originEntity = null, script = null, params = null) {
|
||||
const bundle = await server.post<Bundle>(`script/bundle/${noteId}`, {
|
||||
script,
|
||||
params
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import { t } from "./i18n.js";
|
||||
import toast from "./toast.js";
|
||||
|
||||
export function copyText(text: string) {
|
||||
if (!text) {
|
||||
return;
|
||||
@@ -9,26 +6,29 @@ export function copyText(text: string) {
|
||||
if (navigator.clipboard) {
|
||||
navigator.clipboard.writeText(text);
|
||||
return true;
|
||||
}
|
||||
// Fallback method: https://stackoverflow.com/a/72239825
|
||||
const textArea = document.createElement("textarea");
|
||||
textArea.value = text;
|
||||
try {
|
||||
document.body.appendChild(textArea);
|
||||
textArea.focus();
|
||||
textArea.select();
|
||||
return document.execCommand('copy');
|
||||
} finally {
|
||||
document.body.removeChild(textArea);
|
||||
} else {
|
||||
// Fallback method: https://stackoverflow.com/a/72239825
|
||||
const textArea = document.createElement("textarea");
|
||||
textArea.value = text;
|
||||
try {
|
||||
document.body.appendChild(textArea);
|
||||
textArea.focus();
|
||||
textArea.select();
|
||||
return document.execCommand('copy');
|
||||
} finally {
|
||||
document.body.removeChild(textArea);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
console.warn(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function copyTextWithToast(text: string) {
|
||||
export async function copyTextWithToast(text: string) {
|
||||
const t = (await import("./i18n.js")).t;
|
||||
const toast = (await import("./toast.js")).default;
|
||||
|
||||
if (copyText(text)) {
|
||||
toast.showMessage(t("clipboard.copy_success"));
|
||||
} else {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import "./content_renderer.css";
|
||||
|
||||
import { normalizeMimeTypeForCKEditor, type TextRepresentationResponse } from "@triliumnext/commons";
|
||||
import { normalizeMimeTypeForCKEditor } from "@triliumnext/commons";
|
||||
import { h, render } from "preact";
|
||||
import WheelZoom from 'vanilla-js-wheel-zoom';
|
||||
|
||||
@@ -15,7 +15,6 @@ import openService from "./open.js";
|
||||
import protectedSessionService from "./protected_session.js";
|
||||
import protectedSessionHolder from "./protected_session_holder.js";
|
||||
import renderService from "./render.js";
|
||||
import server from "./server.js";
|
||||
import { applySingleBlockSyntaxHighlight } from "./syntax_highlight.js";
|
||||
import utils, { getErrorMessage } from "./utils.js";
|
||||
|
||||
@@ -33,7 +32,6 @@ export interface RenderOptions {
|
||||
includeArchivedNotes?: boolean;
|
||||
/** Set of note IDs that have already been seen during rendering to prevent infinite recursion. */
|
||||
seenNoteIds?: Set<string>;
|
||||
showTextRepresentation?: boolean;
|
||||
}
|
||||
|
||||
const CODE_MIME_TYPES = new Set(["application/json"]);
|
||||
@@ -57,9 +55,9 @@ export async function getRenderedContent(this: {} | { ctx: string }, entity: FNo
|
||||
} else if (type === "code") {
|
||||
await renderCode(entity, $renderedContent);
|
||||
} else if (["image", "canvas", "mindMap", "spreadsheet"].includes(type)) {
|
||||
await renderImage(entity, $renderedContent, options);
|
||||
renderImage(entity, $renderedContent, options);
|
||||
} else if (!options.tooltip && ["file", "pdf", "audio", "video"].includes(type)) {
|
||||
await renderFile(entity, type, $renderedContent, options);
|
||||
await renderFile(entity, type, $renderedContent);
|
||||
} else if (type === "mermaid") {
|
||||
await renderMermaid(entity, $renderedContent);
|
||||
} else if (type === "render" && entity instanceof FNote) {
|
||||
@@ -140,7 +138,7 @@ async function renderCode(note: FNote | FAttachment, $renderedContent: JQuery<HT
|
||||
await applySingleBlockSyntaxHighlight($codeBlock, normalizeMimeTypeForCKEditor(note.mime));
|
||||
}
|
||||
|
||||
async function renderImage(entity: FNote | FAttachment, $renderedContent: JQuery<HTMLElement>, options: RenderOptions = {}) {
|
||||
function renderImage(entity: FNote | FAttachment, $renderedContent: JQuery<HTMLElement>, options: RenderOptions = {}) {
|
||||
const encodedTitle = encodeURIComponent(entity.title);
|
||||
|
||||
let url;
|
||||
@@ -148,14 +146,13 @@ async function renderImage(entity: FNote | FAttachment, $renderedContent: JQuery
|
||||
if (entity instanceof FNote) {
|
||||
url = `api/images/${entity.noteId}/${encodedTitle}?${Math.random()}`;
|
||||
} else if (entity instanceof FAttachment) {
|
||||
url = `api/attachments/${entity.attachmentId}/image/${encodedTitle}?${entity.utcDateModified}`;
|
||||
url = `api/attachments/${entity.attachmentId}/image/${encodedTitle}?${entity.utcDateModified}">`;
|
||||
}
|
||||
|
||||
$renderedContent // styles needed for the zoom to work well
|
||||
.css("display", "flex")
|
||||
.css("align-items", "center")
|
||||
.css("justify-content", "center")
|
||||
.css("flex-direction", "column"); // OCR text is displayed below the image.
|
||||
.css("justify-content", "center");
|
||||
|
||||
const $img = $("<img>")
|
||||
.attr("src", url || "")
|
||||
@@ -181,35 +178,9 @@ async function renderImage(entity: FNote | FAttachment, $renderedContent: JQuery
|
||||
}
|
||||
|
||||
imageContextMenuService.setupContextMenu($img);
|
||||
|
||||
if (entity instanceof FNote && options.showTextRepresentation) {
|
||||
await addOCRTextIfAvailable(entity, $renderedContent);
|
||||
}
|
||||
}
|
||||
|
||||
async function addOCRTextIfAvailable(note: FNote, $content: JQuery<HTMLElement>) {
|
||||
try {
|
||||
const data = await server.get<TextRepresentationResponse>(`ocr/notes/${note.noteId}/text`);
|
||||
if (data.success && data.hasOcr && data.text) {
|
||||
const $ocrSection = $(`
|
||||
<div class="ocr-text-section">
|
||||
<div class="ocr-header">
|
||||
<span class="bx bx-text"></span> ${t("ocr.extracted_text")}
|
||||
</div>
|
||||
<div class="ocr-content"></div>
|
||||
</div>
|
||||
`);
|
||||
|
||||
$ocrSection.find('.ocr-content').text(data.text);
|
||||
$content.append($ocrSection);
|
||||
}
|
||||
} catch (error) {
|
||||
// Silently fail if OCR API is not available
|
||||
console.debug('Failed to fetch OCR text:', error);
|
||||
}
|
||||
}
|
||||
|
||||
async function renderFile(entity: FNote | FAttachment, type: string, $renderedContent: JQuery<HTMLElement>, options: RenderOptions = {}) {
|
||||
async function renderFile(entity: FNote | FAttachment, type: string, $renderedContent: JQuery<HTMLElement>) {
|
||||
let entityType, entityId;
|
||||
|
||||
if (entity instanceof FNote) {
|
||||
@@ -249,10 +220,6 @@ async function renderFile(entity: FNote | FAttachment, type: string, $renderedCo
|
||||
$content.append($videoPreview);
|
||||
}
|
||||
|
||||
if (entity instanceof FNote && options.showTextRepresentation) {
|
||||
await addOCRTextIfAvailable(entity, $content);
|
||||
}
|
||||
|
||||
if (entityType === "notes" && "noteId" in entity) {
|
||||
// TODO: we should make this available also for attachments, but there's a problem with "Open externally" support
|
||||
// in attachment list
|
||||
|
||||
@@ -84,55 +84,6 @@ async function createSearchNote(opts = {}) {
|
||||
return await froca.getNote(note.noteId);
|
||||
}
|
||||
|
||||
async function createLlmChat() {
|
||||
const note = await server.post<FNoteRow>("special-notes/llm-chat");
|
||||
|
||||
await ws.waitForMaxKnownEntityChangeId();
|
||||
|
||||
return await froca.getNote(note.noteId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the most recently modified LLM chat.
|
||||
* Returns null if no chat exists.
|
||||
*/
|
||||
async function getMostRecentLlmChat() {
|
||||
const note = await server.get<FNoteRow | null>("special-notes/most-recent-llm-chat");
|
||||
|
||||
if (!note) {
|
||||
return null;
|
||||
}
|
||||
|
||||
await ws.waitForMaxKnownEntityChangeId();
|
||||
|
||||
return await froca.getNote(note.noteId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the most recent LLM chat, or creates a new one if none exists.
|
||||
* Used by sidebar chat for persistent conversations across page refreshes.
|
||||
*/
|
||||
async function getOrCreateLlmChat() {
|
||||
const note = await server.get<FNoteRow>("special-notes/get-or-create-llm-chat");
|
||||
|
||||
await ws.waitForMaxKnownEntityChangeId();
|
||||
|
||||
return await froca.getNote(note.noteId);
|
||||
}
|
||||
|
||||
export interface RecentLlmChat {
|
||||
noteId: string;
|
||||
title: string;
|
||||
dateModified: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of recent LLM chats for the history popup.
|
||||
*/
|
||||
async function getRecentLlmChats(limit: number = 10): Promise<RecentLlmChat[]> {
|
||||
return await server.get<RecentLlmChat[]>(`special-notes/recent-llm-chats?limit=${limit}`);
|
||||
}
|
||||
|
||||
export default {
|
||||
getInboxNote,
|
||||
getTodayNote,
|
||||
@@ -143,9 +94,5 @@ export default {
|
||||
getMonthNote,
|
||||
getYearNote,
|
||||
createSqlConsole,
|
||||
createSearchNote,
|
||||
createLlmChat,
|
||||
getMostRecentLlmChat,
|
||||
getOrCreateLlmChat,
|
||||
getRecentLlmChats
|
||||
createSearchNote
|
||||
};
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import { Modal } from "bootstrap";
|
||||
|
||||
import appContext from "../components/app_context.js";
|
||||
import type { ConfirmDialogOptions, ConfirmDialogResult, ConfirmWithMessageOptions, MessageType } from "../widgets/dialogs/confirm.js";
|
||||
import { InfoExtraProps } from "../widgets/dialogs/info.jsx";
|
||||
import type { PromptDialogOptions } from "../widgets/dialogs/prompt.js";
|
||||
import { focusSavedElement, saveFocusedElement } from "./focus.js";
|
||||
import keyboardActionsService from "./keyboard_actions.js";
|
||||
import { InfoExtraProps } from "../widgets/dialogs/info.jsx";
|
||||
|
||||
export async function openDialog($dialog: JQuery<HTMLElement>, closeActDialog = true, config?: Partial<Modal.Options>) {
|
||||
if (closeActDialog) {
|
||||
@@ -27,6 +25,7 @@ export async function openDialog($dialog: JQuery<HTMLElement>, closeActDialog =
|
||||
}
|
||||
});
|
||||
|
||||
const keyboardActionsService = (await import("./keyboard_actions.js")).default;
|
||||
keyboardActionsService.updateDisplayedShortcuts($dialog);
|
||||
|
||||
return $dialog;
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { isValidDocName } from "./doc_renderer.js";
|
||||
|
||||
describe("isValidDocName", () => {
|
||||
it("accepts valid docNames", () => {
|
||||
expect(isValidDocName("launchbar_intro")).toBe(true);
|
||||
expect(isValidDocName("User Guide/Quick Start")).toBe(true);
|
||||
expect(isValidDocName("User Guide/User Guide/Quick Start")).toBe(true);
|
||||
expect(isValidDocName("Quick Start Guide")).toBe(true);
|
||||
expect(isValidDocName("quick_start_guide")).toBe(true);
|
||||
expect(isValidDocName("quick-start-guide")).toBe(true);
|
||||
});
|
||||
|
||||
it("rejects path traversal attacks", () => {
|
||||
expect(isValidDocName("..")).toBe(false);
|
||||
expect(isValidDocName("../etc/passwd")).toBe(false);
|
||||
expect(isValidDocName("foo/../bar")).toBe(false);
|
||||
expect(isValidDocName("../../../../api/notes/_malicious/open")).toBe(false);
|
||||
expect(isValidDocName("..\\etc\\passwd")).toBe(false);
|
||||
expect(isValidDocName("foo\\bar")).toBe(false);
|
||||
});
|
||||
|
||||
it("rejects URL manipulation attacks", () => {
|
||||
expect(isValidDocName("../../../../api/notes/_malicious/open?x=")).toBe(false);
|
||||
expect(isValidDocName("foo#bar")).toBe(false);
|
||||
expect(isValidDocName("%2e%2e")).toBe(false);
|
||||
expect(isValidDocName("%2e%2e%2f%2e%2e%2fapi")).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -3,39 +3,22 @@ import { applyReferenceLinks } from "../widgets/type_widgets/text/read_only_help
|
||||
import { getCurrentLanguage } from "./i18n.js";
|
||||
import { formatCodeBlocks } from "./syntax_highlight.js";
|
||||
|
||||
/**
|
||||
* Validates a docName to prevent path traversal attacks.
|
||||
* Allows forward slashes for subdirectories (e.g., "User Guide/Quick Start")
|
||||
* but blocks traversal sequences and URL manipulation characters.
|
||||
*/
|
||||
export function isValidDocName(docName: string): boolean {
|
||||
// Allow alphanumeric characters, spaces, underscores, hyphens, and forward slashes.
|
||||
const validDocNameRegex = /^[a-zA-Z0-9_/\- ]+$/;
|
||||
return validDocNameRegex.test(docName);
|
||||
}
|
||||
|
||||
export default function renderDoc(note: FNote) {
|
||||
return new Promise<JQuery<HTMLElement>>((resolve) => {
|
||||
const docName = note.getLabelValue("docName");
|
||||
let docName = note.getLabelValue("docName");
|
||||
const $content = $("<div>");
|
||||
|
||||
// find doc based on language
|
||||
const url = getUrl(docName, getCurrentLanguage());
|
||||
|
||||
if (url) {
|
||||
if (docName) {
|
||||
// find doc based on language
|
||||
const url = getUrl(docName, getCurrentLanguage());
|
||||
$content.load(url, async (response, status) => {
|
||||
// fallback to english doc if no translation available
|
||||
if (status === "error") {
|
||||
const fallbackUrl = getUrl(docName, "en");
|
||||
|
||||
if (fallbackUrl) {
|
||||
$content.load(fallbackUrl, async () => {
|
||||
await processContent(fallbackUrl, $content);
|
||||
resolve($content);
|
||||
});
|
||||
} else {
|
||||
$content.load(fallbackUrl, async () => {
|
||||
await processContent(fallbackUrl, $content)
|
||||
resolve($content);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -45,6 +28,8 @@ export default function renderDoc(note: FNote) {
|
||||
} else {
|
||||
resolve($content);
|
||||
}
|
||||
|
||||
return $content;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -54,7 +39,7 @@ async function processContent(url: string, $content: JQuery<HTMLElement>) {
|
||||
// Images are relative to the docnote but that will not work when rendered in the application since the path breaks.
|
||||
$content.find("img").each((i, el) => {
|
||||
const $img = $(el);
|
||||
$img.attr("src", `${dir}/${$img.attr("src")}`);
|
||||
$img.attr("src", dir + "/" + $img.attr("src"));
|
||||
});
|
||||
|
||||
formatCodeBlocks($content);
|
||||
@@ -63,17 +48,10 @@ async function processContent(url: string, $content: JQuery<HTMLElement>) {
|
||||
await applyReferenceLinks($content[0]);
|
||||
}
|
||||
|
||||
function getUrl(docNameValue: string | null, language: string) {
|
||||
if (!docNameValue) return;
|
||||
|
||||
if (!isValidDocName(docNameValue)) {
|
||||
console.error(`Invalid docName: ${docNameValue}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
function getUrl(docNameValue: string, language: string) {
|
||||
// Cannot have spaces in the URL due to how JQuery.load works.
|
||||
docNameValue = docNameValue.replaceAll(" ", "%20");
|
||||
|
||||
const basePath = window.glob.isDev ? `${window.glob.assetPath }/..` : window.glob.assetPath;
|
||||
const basePath = window.glob.isDev ? window.glob.assetPath + "/.." : window.glob.assetPath;
|
||||
return `${basePath}/doc_notes/${language}/${docNameValue}.html`;
|
||||
}
|
||||
|
||||
@@ -13,11 +13,6 @@ export const experimentalFeatures = [
|
||||
id: "new-layout",
|
||||
name: t("experimental_features.new_layout_name"),
|
||||
description: t("experimental_features.new_layout_description"),
|
||||
},
|
||||
{
|
||||
id: "llm",
|
||||
name: t("experimental_features.llm_name"),
|
||||
description: t("experimental_features.llm_description"),
|
||||
}
|
||||
] as const satisfies ExperimentalFeature[];
|
||||
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
import type { OptionNames } from "@triliumnext/commons";
|
||||
|
||||
import appContext from "../components/app_context.js";
|
||||
import FAttachment, { type FAttachmentRow } from "../entities/fattachment.js";
|
||||
import FAttribute, { type FAttributeRow } from "../entities/fattribute.js";
|
||||
import LoadResults from "./load_results.js";
|
||||
import froca from "./froca.js";
|
||||
import utils from "./utils.js";
|
||||
import options from "./options.js";
|
||||
import noteAttributeCache from "./note_attribute_cache.js";
|
||||
import FBranch, { type FBranchRow } from "../entities/fbranch.js";
|
||||
import FAttribute, { type FAttributeRow } from "../entities/fattribute.js";
|
||||
import FAttachment, { type FAttachmentRow } from "../entities/fattachment.js";
|
||||
import type { default as FNote, FNoteRow } from "../entities/fnote.js";
|
||||
import type { EntityChange } from "../server_types.js";
|
||||
import froca from "./froca.js";
|
||||
import LoadResults from "./load_results.js";
|
||||
import noteAttributeCache from "./note_attribute_cache.js";
|
||||
import options from "./options.js";
|
||||
import utils from "./utils.js";
|
||||
import type { OptionNames } from "@triliumnext/commons";
|
||||
|
||||
async function processEntityChanges(entityChanges: EntityChange[]) {
|
||||
const loadResults = new LoadResults(entityChanges);
|
||||
@@ -65,7 +63,7 @@ async function processEntityChanges(entityChanges: EntityChange[]) {
|
||||
if (entityName === "branches" && !((entity as FBranchRow).parentNoteId in froca.notes)) {
|
||||
missingNoteIds.push((entity as FBranchRow).parentNoteId);
|
||||
} else if (entityName === "attributes") {
|
||||
const attributeEntity = entity as FAttributeRow;
|
||||
let attributeEntity = entity as FAttributeRow;
|
||||
if (attributeEntity.type === "relation" && (attributeEntity.name === "template" || attributeEntity.name === "inherit") && !(attributeEntity.value in froca.notes)) {
|
||||
missingNoteIds.push(attributeEntity.value);
|
||||
}
|
||||
@@ -81,6 +79,7 @@ async function processEntityChanges(entityChanges: EntityChange[]) {
|
||||
noteAttributeCache.invalidate();
|
||||
}
|
||||
|
||||
const appContext = (await import("../components/app_context.js")).default;
|
||||
await appContext.triggerEvent("entitiesReloaded", { loadResults });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { createContext, Fragment, h, VNode } from "preact";
|
||||
import { Fragment, h, VNode } from "preact";
|
||||
import * as hooks from "preact/hooks";
|
||||
|
||||
import ActionButton from "../widgets/react/ActionButton";
|
||||
@@ -47,7 +47,6 @@ export const preactAPI = Object.freeze({
|
||||
// Core
|
||||
h,
|
||||
Fragment,
|
||||
createContext,
|
||||
|
||||
/**
|
||||
* Method that must be run for widget scripts that run on Preact, using JSX. The method just returns the same definition, reserved for future typechecking and perhaps validation purposes.
|
||||
|
||||
@@ -1,14 +1,21 @@
|
||||
import { LOCALE_IDS, LOCALES, setDayjsLocale } from "@triliumnext/commons";
|
||||
import options from "./options.js";
|
||||
import i18next from "i18next";
|
||||
import i18nextHttpBackend from "i18next-http-backend";
|
||||
import server from "./server.js";
|
||||
import { LOCALE_IDS, setDayjsLocale, type Locale } from "@triliumnext/commons";
|
||||
import { initReactI18next } from "react-i18next";
|
||||
|
||||
let locales: Locale[] | null;
|
||||
|
||||
/**
|
||||
* A deferred promise that resolves when translations are initialized.
|
||||
*/
|
||||
export const translationsInitializedPromise = $.Deferred();
|
||||
export let translationsInitializedPromise = $.Deferred();
|
||||
|
||||
export async function initLocale(locale: LOCALE_IDS = "en") {
|
||||
export async function initLocale() {
|
||||
const locale = ((options.get("locale") as string) || "en") as LOCALE_IDS;
|
||||
|
||||
locales = await server.get<Locale[]>("options/locales");
|
||||
|
||||
i18next.use(initReactI18next);
|
||||
await i18next.use(i18nextHttpBackend).init({
|
||||
@@ -17,7 +24,8 @@ export async function initLocale(locale: LOCALE_IDS = "en") {
|
||||
backend: {
|
||||
loadPath: `${window.glob.assetPath}/translations/{{lng}}/{{ns}}.json`
|
||||
},
|
||||
returnEmptyString: false
|
||||
returnEmptyString: false,
|
||||
showSupportNotice: false
|
||||
});
|
||||
|
||||
await setDayjsLocale(locale);
|
||||
@@ -25,7 +33,11 @@ export async function initLocale(locale: LOCALE_IDS = "en") {
|
||||
}
|
||||
|
||||
export function getAvailableLocales() {
|
||||
return LOCALES;
|
||||
if (!locales) {
|
||||
throw new Error("Tried to load list of locales, but localization is not yet initialized.")
|
||||
}
|
||||
|
||||
return locales;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,7 +48,7 @@ export function getAvailableLocales() {
|
||||
*/
|
||||
export function getLocaleById(localeId: string | null | undefined) {
|
||||
if (!localeId) return null;
|
||||
return LOCALES.find((l) => l.id === localeId) ?? null;
|
||||
return locales?.find((l) => l.id === localeId) ?? null;
|
||||
}
|
||||
|
||||
export const t = i18next.t;
|
||||
|
||||
@@ -19,8 +19,7 @@ export const byNoteType: Record<Exclude<NoteType, "book">, string | null> = {
|
||||
search: null,
|
||||
text: null,
|
||||
webView: null,
|
||||
spreadsheet: null,
|
||||
llmChat: null
|
||||
spreadsheet: null
|
||||
};
|
||||
|
||||
export const byBookType: Record<ViewTypeOptions, string | null> = {
|
||||
|
||||
@@ -28,7 +28,7 @@ async function getLinkIcon(noteId: string, viewMode: ViewMode | undefined) {
|
||||
return icon;
|
||||
}
|
||||
|
||||
export type ViewMode = "default" | "source" | "attachments" | "contextual-help" | "note-map" | "ocr";
|
||||
export type ViewMode = "default" | "source" | "attachments" | "contextual-help" | "note-map";
|
||||
|
||||
export interface ViewScope {
|
||||
/**
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
import type { LlmChatConfig, LlmCitation, LlmMessage, LlmModelInfo,LlmUsage } from "@triliumnext/commons";
|
||||
|
||||
import server from "./server.js";
|
||||
|
||||
/**
|
||||
* Fetch available models from all configured providers.
|
||||
*/
|
||||
export async function getAvailableModels(): Promise<LlmModelInfo[]> {
|
||||
const response = await server.get<{ models?: LlmModelInfo[] }>("llm-chat/models");
|
||||
return response.models ?? [];
|
||||
}
|
||||
|
||||
export interface StreamCallbacks {
|
||||
onChunk: (text: string) => void;
|
||||
onThinking?: (text: string) => void;
|
||||
onToolUse?: (toolName: string, input: Record<string, unknown>) => void;
|
||||
onToolResult?: (toolName: string, result: string, isError?: boolean) => void;
|
||||
onCitation?: (citation: LlmCitation) => void;
|
||||
onUsage?: (usage: LlmUsage) => void;
|
||||
onError: (error: string) => void;
|
||||
onDone: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stream a chat completion from the LLM API using Server-Sent Events.
|
||||
*/
|
||||
export async function streamChatCompletion(
|
||||
messages: LlmMessage[],
|
||||
config: LlmChatConfig,
|
||||
callbacks: StreamCallbacks,
|
||||
abortSignal?: AbortSignal
|
||||
): Promise<void> {
|
||||
const headers = await server.getHeaders();
|
||||
|
||||
const response = await fetch(`${window.glob.baseApiUrl}llm-chat/stream`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
...headers,
|
||||
"Content-Type": "application/json"
|
||||
} as HeadersInit,
|
||||
body: JSON.stringify({ messages, config }),
|
||||
signal: abortSignal
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
callbacks.onError(`HTTP ${response.status}: ${response.statusText}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const reader = response.body?.getReader();
|
||||
if (!reader) {
|
||||
callbacks.onError("No response body");
|
||||
return;
|
||||
}
|
||||
|
||||
const decoder = new TextDecoder();
|
||||
let buffer = "";
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
const { done, value } = await reader.read();
|
||||
if (done) break;
|
||||
|
||||
buffer += decoder.decode(value, { stream: true });
|
||||
const lines = buffer.split("\n");
|
||||
buffer = lines.pop() || "";
|
||||
|
||||
for (const line of lines) {
|
||||
if (line.startsWith("data: ")) {
|
||||
try {
|
||||
const data = JSON.parse(line.slice(6));
|
||||
|
||||
switch (data.type) {
|
||||
case "text":
|
||||
callbacks.onChunk(data.content);
|
||||
break;
|
||||
case "thinking":
|
||||
callbacks.onThinking?.(data.content);
|
||||
break;
|
||||
case "tool_use":
|
||||
callbacks.onToolUse?.(data.toolName, data.toolInput);
|
||||
// Yield to force Preact to commit the pending tool call
|
||||
// state before we process the result.
|
||||
await new Promise((r) => setTimeout(r, 1));
|
||||
break;
|
||||
case "tool_result":
|
||||
callbacks.onToolResult?.(data.toolName, data.result, data.isError);
|
||||
await new Promise((r) => setTimeout(r, 1));
|
||||
break;
|
||||
case "citation":
|
||||
if (data.citation) {
|
||||
callbacks.onCitation?.(data.citation);
|
||||
}
|
||||
break;
|
||||
case "usage":
|
||||
if (data.usage) {
|
||||
callbacks.onUsage?.(data.usage);
|
||||
}
|
||||
break;
|
||||
case "error":
|
||||
callbacks.onError(data.error);
|
||||
break;
|
||||
case "done":
|
||||
callbacks.onDone();
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Failed to parse SSE data line:", line, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
reader.releaseLock();
|
||||
}
|
||||
}
|
||||
@@ -68,8 +68,7 @@ async function autocompleteSourceForCKEditor(queryText: string) {
|
||||
name: row.notePathTitle || "",
|
||||
link: `#${row.notePath}`,
|
||||
notePath: row.notePath,
|
||||
highlightedNotePathTitle: row.highlightedNotePathTitle,
|
||||
icon: row.icon
|
||||
highlightedNotePathTitle: row.highlightedNotePathTitle
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
@@ -67,6 +67,14 @@ async function createNote(parentNotePath: string | undefined, options: CreateNot
|
||||
|
||||
const parentNoteId = treeService.getNoteIdFromUrl(parentNotePath);
|
||||
|
||||
if (options.type === "mermaid" && !options.content && !options.templateNoteId) {
|
||||
options.content = `graph TD;
|
||||
A-->B;
|
||||
A-->C;
|
||||
B-->D;
|
||||
C-->D;`;
|
||||
}
|
||||
|
||||
const { note, branch } = await server.post<Response>(`notes/${parentNoteId}/children?target=${options.target}&targetBranchId=${options.targetBranchId || ""}`, {
|
||||
title: options.title,
|
||||
content: options.content || "",
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import type { NoteType } from "../entities/fnote.js";
|
||||
import type { MenuCommandItem, MenuItem, MenuItemBadge, MenuSeparatorItem } from "../menus/context_menu.js";
|
||||
import type { TreeCommandNames } from "../menus/tree_context_menu.js";
|
||||
import { isExperimentalFeatureEnabled } from "./experimental_features.js";
|
||||
import froca from "./froca.js";
|
||||
import { t } from "./i18n.js";
|
||||
import server from "./server.js";
|
||||
@@ -42,7 +41,6 @@ export const NOTE_TYPES: NoteTypeMapping[] = [
|
||||
{ type: "relationMap", mime: "application/json", title: t("note_types.relation-map"), icon: "bxs-network-chart" },
|
||||
|
||||
// Misc note types
|
||||
{ type: "llmChat", mime: "application/json", title: t("note_types.llm-chat"), icon: "bx-message-square-dots", isBeta: true },
|
||||
{ type: "render", mime: "", title: t("note_types.render-note"), icon: "bx-extension" },
|
||||
{ type: "search", title: t("note_types.saved-search"), icon: "bx-file-find", static: true },
|
||||
{ type: "webView", mime: "", title: t("note_types.web-view"), icon: "bx-globe-alt" },
|
||||
@@ -94,7 +92,6 @@ async function getNoteTypeItems(command?: TreeCommandNames) {
|
||||
function getBlankNoteTypes(command?: TreeCommandNames): MenuItem<TreeCommandNames>[] {
|
||||
return NOTE_TYPES
|
||||
.filter((nt) => !nt.reserved && nt.type !== "book")
|
||||
.filter((nt) => nt.type !== "llmChat" || isExperimentalFeatureEnabled("llm"))
|
||||
.map((nt) => {
|
||||
const menuItem: MenuCommandItem<TreeCommandNames> = {
|
||||
title: nt.title,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export type LabelType = "text" | "textarea" | "number" | "boolean" | "date" | "datetime" | "time" | "url" | "color";
|
||||
export type LabelType = "text" | "number" | "boolean" | "date" | "datetime" | "time" | "url" | "color";
|
||||
type Multiplicity = "single" | "multi";
|
||||
|
||||
export interface DefinitionObject {
|
||||
@@ -17,7 +17,7 @@ function parse(value: string) {
|
||||
for (const token of tokens) {
|
||||
if (token === "promoted") {
|
||||
defObj.isPromoted = true;
|
||||
} else if (["text", "textarea", "number", "boolean", "date", "datetime", "time", "url", "color"].includes(token)) {
|
||||
} else if (["text", "number", "boolean", "date", "datetime", "time", "url", "color"].includes(token)) {
|
||||
defObj.labelType = token as LabelType;
|
||||
} else if (["single", "multi"].includes(token)) {
|
||||
defObj.multiplicity = token as Multiplicity;
|
||||
|
||||
@@ -18,10 +18,6 @@ async function render(note: FNote, $el: JQuery<HTMLElement>, onError?: ErrorHand
|
||||
for (const renderNoteId of renderNoteIds) {
|
||||
const bundle = await server.postWithSilentInternalServerError<Bundle>(`script/bundle/${renderNoteId}`);
|
||||
|
||||
if (!bundle) {
|
||||
throw new Error(`Script note '${renderNoteId}' could not be loaded. It may be protected and require an active protected session.`);
|
||||
}
|
||||
|
||||
const $scriptContainer = $("<div>");
|
||||
$el.append($scriptContainer);
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { t } from "./i18n.js";
|
||||
import utils, { isShare } from "./utils.js";
|
||||
import ValidationError from "./validation_error.js";
|
||||
|
||||
@@ -33,7 +32,8 @@ async function getHeaders(headers?: Headers) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const activeNoteContext = glob.appContext?.tabManager ? glob.appContext.tabManager.getActiveContext() : null;
|
||||
const appContext = (await import("../components/app_context.js")).default;
|
||||
const activeNoteContext = appContext.tabManager ? appContext.tabManager.getActiveContext() : null;
|
||||
|
||||
// headers need to be lowercase because node.js automatically converts them to lower case
|
||||
// also avoiding using underscores instead of dashes since nginx filters them out by default
|
||||
@@ -93,7 +93,7 @@ async function upload(url: string, fileToUpload: File, componentId?: string, met
|
||||
const formData = new FormData();
|
||||
formData.append("upload", fileToUpload);
|
||||
|
||||
const doUpload = async () => $.ajax({
|
||||
return await $.ajax({
|
||||
url: window.glob.baseApiUrl + url,
|
||||
headers: await getHeaders(componentId ? {
|
||||
"trilium-component-id": componentId
|
||||
@@ -104,18 +104,6 @@ async function upload(url: string, fileToUpload: File, componentId?: string, met
|
||||
contentType: false, // NEEDED, DON'T REMOVE THIS
|
||||
processData: false // NEEDED, DON'T REMOVE THIS
|
||||
});
|
||||
|
||||
try {
|
||||
return await doUpload();
|
||||
} catch (e: unknown) {
|
||||
// jQuery rejects with the jqXHR object
|
||||
const jqXhr = e as JQuery.jqXHR;
|
||||
if (jqXhr?.status && isCsrfError(jqXhr.status, jqXhr.responseText)) {
|
||||
await refreshCsrfToken();
|
||||
return await doUpload();
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
let idCounter = 1;
|
||||
@@ -124,55 +112,12 @@ const idToRequestMap: Record<string, RequestData> = {};
|
||||
|
||||
let maxKnownEntityChangeId = 0;
|
||||
|
||||
let csrfRefreshInProgress: Promise<void> | null = null;
|
||||
|
||||
/**
|
||||
* Re-fetches /bootstrap to obtain a fresh CSRF token. This is needed when the
|
||||
* server session expires (e.g. mobile tab backgrounded for a long time) and the
|
||||
* existing CSRF token is no longer valid.
|
||||
*
|
||||
* Coalesces concurrent calls so only one bootstrap request is in-flight at a time.
|
||||
*/
|
||||
async function refreshCsrfToken(): Promise<void> {
|
||||
if (csrfRefreshInProgress) {
|
||||
return csrfRefreshInProgress;
|
||||
}
|
||||
|
||||
csrfRefreshInProgress = (async () => {
|
||||
try {
|
||||
const response = await fetch(`./bootstrap${window.location.search}`, { cache: "no-store" });
|
||||
if (response.ok) {
|
||||
const json = await response.json();
|
||||
glob.csrfToken = json.csrfToken;
|
||||
}
|
||||
} finally {
|
||||
csrfRefreshInProgress = null;
|
||||
}
|
||||
})();
|
||||
|
||||
return csrfRefreshInProgress;
|
||||
}
|
||||
|
||||
function isCsrfError(status: number, responseText: string): boolean {
|
||||
if (status !== 403) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
const body = JSON.parse(responseText);
|
||||
return body.message === "Invalid CSRF token";
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
/** Used internally to prevent infinite retry loops on CSRF refresh. */
|
||||
csrfRetried?: boolean;
|
||||
}
|
||||
|
||||
async function call<T>(method: string, url: string, componentId?: string, options: CallOptions = {}) {
|
||||
@@ -222,7 +167,7 @@ function ajax(url: string, method: string, data: unknown, headers: Headers, opts
|
||||
type: method,
|
||||
headers,
|
||||
timeout: 60000,
|
||||
success: (body, _textStatus, jqXhr) => {
|
||||
success: (body, textStatus, jqXhr) => {
|
||||
const respHeaders: Headers = {};
|
||||
|
||||
jqXhr
|
||||
@@ -247,34 +192,12 @@ function ajax(url: string, method: string, data: unknown, headers: Headers, opts
|
||||
// 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;
|
||||
}
|
||||
|
||||
// If the CSRF token is stale (e.g. session expired while tab was backgrounded),
|
||||
// refresh it and retry the request once.
|
||||
if (!opts.csrfRetried && isCsrfError(jqXhr.status, jqXhr.responseText)) {
|
||||
try {
|
||||
await refreshCsrfToken();
|
||||
// Rebuild headers so the fresh glob.csrfToken is picked up
|
||||
const retryHeaders = await getHeaders({ "trilium-component-id": headers["trilium-component-id"] });
|
||||
const retryResult = await ajax(url, method, data, retryHeaders, { ...opts, csrfRetried: true });
|
||||
res(retryResult);
|
||||
return;
|
||||
} catch (retryErr) {
|
||||
rej(retryErr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.silentNotFound && jqXhr.status === 404) {
|
||||
} else if (opts.silentNotFound && jqXhr.status === 404) {
|
||||
// report nothing
|
||||
} else if (opts.silentInternalServerError && jqXhr.status === 500) {
|
||||
// report nothing
|
||||
} else {
|
||||
try {
|
||||
await reportError(method, url, jqXhr.status, jqXhr.responseText);
|
||||
} catch {
|
||||
// reportError may throw (e.g. ValidationError); ensure rej() is still called below.
|
||||
}
|
||||
await reportError(method, url, jqXhr.status, jqXhr.responseText);
|
||||
}
|
||||
|
||||
rej(jqXhr.responseText);
|
||||
@@ -344,7 +267,6 @@ async function reportError(method: string, url: string, statusCode: number, resp
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
// Dynamic import to avoid circular dependency (toast → app_context → options → server).
|
||||
const toastService = (await import("./toast.js")).default;
|
||||
|
||||
const messageStr = (typeof message === "string" ? message : JSON.stringify(message)) || "-";
|
||||
@@ -358,6 +280,7 @@ async function reportError(method: string, url: string, statusCode: number, resp
|
||||
...response
|
||||
});
|
||||
} else {
|
||||
const { t } = await import("./i18n.js");
|
||||
if (statusCode === 400 && (url.includes("%23") || url.includes("%2F"))) {
|
||||
toastService.showPersistent({
|
||||
id: "trafik-blocked",
|
||||
@@ -371,7 +294,8 @@ async function reportError(method: string, url: string, statusCode: number, resp
|
||||
t("server.unknown_http_error_content", { statusCode, method, url, message: messageStr }),
|
||||
15_000);
|
||||
}
|
||||
window.logError(`${statusCode} ${method} ${url} - ${message}`);
|
||||
const { logError } = await import("./ws.js");
|
||||
logError(`${statusCode} ${method} ${url} - ${message}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
import SpacedUpdate from "./spaced_update";
|
||||
|
||||
// Mock logError which is a global in Trilium
|
||||
vi.stubGlobal("logError", vi.fn());
|
||||
|
||||
describe("SpacedUpdate", () => {
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it("should only call updater once per interval even with multiple pending callbacks", async () => {
|
||||
const updater = vi.fn(async () => {
|
||||
// Simulate a slow network request - this is where the race condition occurs
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
});
|
||||
|
||||
const spacedUpdate = new SpacedUpdate(updater, 50);
|
||||
|
||||
// Simulate rapid typing - each keystroke calls scheduleUpdate()
|
||||
// This queues multiple setTimeout callbacks due to recursive scheduleUpdate() calls
|
||||
for (let i = 0; i < 10; i++) {
|
||||
spacedUpdate.scheduleUpdate();
|
||||
// Small delay between keystrokes
|
||||
await vi.advanceTimersByTimeAsync(5);
|
||||
}
|
||||
|
||||
// Advance time past the update interval to trigger the update
|
||||
await vi.advanceTimersByTimeAsync(100);
|
||||
|
||||
// Let the "network request" complete and any pending callbacks run
|
||||
await vi.advanceTimersByTimeAsync(200);
|
||||
|
||||
// The updater should have been called only ONCE, not multiple times
|
||||
// With the bug, multiple pending setTimeout callbacks would all pass the time check
|
||||
// during the async updater call and trigger multiple concurrent requests
|
||||
expect(updater).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("should call updater again if changes occur during the update", async () => {
|
||||
const updater = vi.fn(async () => {
|
||||
await new Promise((resolve) => setTimeout(resolve, 50));
|
||||
});
|
||||
|
||||
const spacedUpdate = new SpacedUpdate(updater, 30);
|
||||
|
||||
// First update
|
||||
spacedUpdate.scheduleUpdate();
|
||||
await vi.advanceTimersByTimeAsync(40);
|
||||
|
||||
// Schedule another update while the first one is in progress
|
||||
spacedUpdate.scheduleUpdate();
|
||||
|
||||
// Let first update complete
|
||||
await vi.advanceTimersByTimeAsync(60);
|
||||
|
||||
// Advance past the interval again for the second update
|
||||
await vi.advanceTimersByTimeAsync(100);
|
||||
|
||||
// Should have been called twice - once for each distinct change period
|
||||
expect(updater).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it("should restore changed flag on error so retry can happen", async () => {
|
||||
const updater = vi.fn()
|
||||
.mockRejectedValueOnce(new Error("Network error"))
|
||||
.mockResolvedValue(undefined);
|
||||
|
||||
const spacedUpdate = new SpacedUpdate(updater, 50);
|
||||
|
||||
spacedUpdate.scheduleUpdate();
|
||||
|
||||
// Advance to trigger first update (which will fail)
|
||||
await vi.advanceTimersByTimeAsync(60);
|
||||
|
||||
// The error should have restored the changed flag, so scheduling again should work
|
||||
spacedUpdate.scheduleUpdate();
|
||||
await vi.advanceTimersByTimeAsync(60);
|
||||
|
||||
expect(updater).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
});
|
||||
@@ -77,22 +77,16 @@ export default class SpacedUpdate {
|
||||
}
|
||||
|
||||
if (Date.now() - this.lastUpdated > this.updateInterval) {
|
||||
// Update these BEFORE the async call to prevent race conditions.
|
||||
// Multiple setTimeout callbacks may be pending from recursive scheduleUpdate() calls.
|
||||
// Without this, they would all pass the time check during the await and trigger multiple requests.
|
||||
this.lastUpdated = Date.now();
|
||||
this.changed = false;
|
||||
|
||||
this.onStateChanged("saving");
|
||||
try {
|
||||
await this.updater();
|
||||
this.onStateChanged("saved");
|
||||
this.changed = false;
|
||||
} catch (e) {
|
||||
// Restore changed flag on error so a retry can happen
|
||||
this.changed = true;
|
||||
this.onStateChanged("error");
|
||||
logError(getErrorMessage(e));
|
||||
}
|
||||
this.lastUpdated = Date.now();
|
||||
} else {
|
||||
// update isn't triggered but changes are still pending, so we need to schedule another check
|
||||
this.scheduleUpdate();
|
||||
|
||||
@@ -33,14 +33,6 @@ export async function formatCodeBlocks($container: JQuery<HTMLElement>) {
|
||||
applySingleBlockSyntaxHighlight($(codeBlock), normalizedMimeType);
|
||||
}
|
||||
}
|
||||
|
||||
// Add click-to-copy for inline code (code elements not inside pre)
|
||||
if (glob.device !== "print") {
|
||||
const inlineCodeElements = $container.find("code:not(pre code)");
|
||||
for (const inlineCode of inlineCodeElements) {
|
||||
applyInlineCodeCopy($(inlineCode));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function applyCopyToClipboardButton($codeBlock: JQuery<HTMLElement>) {
|
||||
@@ -59,23 +51,6 @@ export function applyCopyToClipboardButton($codeBlock: JQuery<HTMLElement>) {
|
||||
$codeBlock.parent().append($copyButton);
|
||||
}
|
||||
|
||||
export function applyInlineCodeCopy($inlineCode: JQuery<HTMLElement>) {
|
||||
$inlineCode
|
||||
.addClass("copyable-inline-code")
|
||||
.attr("title", t("code_block.click_to_copy"))
|
||||
.off("click")
|
||||
.on("click", (e) => {
|
||||
e.stopPropagation();
|
||||
|
||||
const text = $inlineCode.text();
|
||||
if (!isShare) {
|
||||
copyTextWithToast(text);
|
||||
} else {
|
||||
copyText(text);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies syntax highlight to the given code block (assumed to be <pre><code>), using highlight.js.
|
||||
*/
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
export function getThemeStyle(): "auto" | "light" | "dark" {
|
||||
const configuredTheme = window.glob?.theme;
|
||||
if (configuredTheme === "auto" || configuredTheme === "next") {
|
||||
return "auto";
|
||||
}
|
||||
|
||||
if (configuredTheme === "light" || configuredTheme === "dark") {
|
||||
return configuredTheme;
|
||||
}
|
||||
|
||||
if (configuredTheme === "next-light") {
|
||||
return "light";
|
||||
}
|
||||
|
||||
if (configuredTheme === "next-dark") {
|
||||
return "dark";
|
||||
}
|
||||
|
||||
const style = window.getComputedStyle(document.body);
|
||||
const themeStyle = style.getPropertyValue("--theme-style");
|
||||
if (style.getPropertyValue("--theme-style-auto") !== "true" && (themeStyle === "light" || themeStyle === "dark")) {
|
||||
return themeStyle as "light" | "dark";
|
||||
}
|
||||
|
||||
return "auto";
|
||||
}
|
||||
|
||||
export function getEffectiveThemeStyle(): "light" | "dark" {
|
||||
const themeStyle = getThemeStyle();
|
||||
if (themeStyle === "auto") {
|
||||
return window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
||||
}
|
||||
|
||||
return themeStyle === "dark" ? "dark" : "light";
|
||||
}
|
||||
@@ -455,7 +455,9 @@ export function openInAppHelpFromUrl(inAppHelpPage: string) {
|
||||
export async function openInReusableSplit(targetNoteId: string, targetViewMode: ViewMode, openOpts: {
|
||||
hoistedNoteId?: string;
|
||||
} = {}) {
|
||||
const activeContext = glob.appContext?.tabManager?.getActiveContext();
|
||||
// Dynamic import to avoid import issues in tests.
|
||||
const appContext = (await import("../components/app_context.js")).default;
|
||||
const activeContext = appContext.tabManager.getActiveContext();
|
||||
if (!activeContext) {
|
||||
return;
|
||||
}
|
||||
@@ -465,7 +467,7 @@ export async function openInReusableSplit(targetNoteId: string, targetViewMode:
|
||||
if (!existingSubcontext) {
|
||||
// The target split is not already open, open a new split with it.
|
||||
const { ntxId } = subContexts[subContexts.length - 1];
|
||||
glob.appContext?.triggerCommand("openNewNoteSplit", {
|
||||
appContext.triggerCommand("openNewNoteSplit", {
|
||||
ntxId,
|
||||
notePath: targetNoteId,
|
||||
hoistedNoteId: openOpts.hoistedNoteId,
|
||||
@@ -920,7 +922,6 @@ export default {
|
||||
parseDate,
|
||||
formatDateISO,
|
||||
formatDateTime,
|
||||
formatTime,
|
||||
formatTimeInterval,
|
||||
formatSize,
|
||||
localNowDateTime,
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
import { WebSocketMessage } from "@triliumnext/commons";
|
||||
|
||||
import appContext from "../components/app_context.js";
|
||||
import type { EntityChange } from "../server_types.js";
|
||||
import bundleService from "./bundle.js";
|
||||
import froca from "./froca.js";
|
||||
import frocaUpdater from "./froca_updater.js";
|
||||
import { t } from "./i18n.js";
|
||||
import options from "./options.js";
|
||||
import server from "./server.js";
|
||||
import toast from "./toast.js";
|
||||
import utils from "./utils.js";
|
||||
import toastService from "./toast.js";
|
||||
import server from "./server.js";
|
||||
import options from "./options.js";
|
||||
import frocaUpdater from "./froca_updater.js";
|
||||
import appContext from "../components/app_context.js";
|
||||
import { t } from "./i18n.js";
|
||||
import type { EntityChange } from "../server_types.js";
|
||||
import { WebSocketMessage } from "@triliumnext/commons";
|
||||
import toast from "./toast.js";
|
||||
|
||||
type MessageHandler = (message: WebSocketMessage) => void;
|
||||
let messageHandlers: MessageHandler[] = [];
|
||||
@@ -128,14 +126,20 @@ async function handleMessage(event: MessageEvent<any>) {
|
||||
} else if (message.type === "frontend-update") {
|
||||
await executeFrontendUpdate(message.data.entityChanges);
|
||||
} else if (message.type === "sync-hash-check-failed") {
|
||||
toast.showError(t("ws.sync-check-failed"), 60000);
|
||||
toastService.showError(t("ws.sync-check-failed"), 60000);
|
||||
} else if (message.type === "consistency-checks-failed") {
|
||||
toast.showError(t("ws.consistency-checks-failed"), 50 * 60000);
|
||||
toastService.showError(t("ws.consistency-checks-failed"), 50 * 60000);
|
||||
} else if (message.type === "api-log-messages") {
|
||||
appContext.triggerEvent("apiLogMessages", { noteId: message.noteId, messages: message.messages });
|
||||
} else if (message.type === "toast") {
|
||||
toast.showMessage(message.message, message.timeout);
|
||||
toastService.showMessage(message.message);
|
||||
} else if (message.type === "execute-script") {
|
||||
// TODO: Remove after porting the file
|
||||
// @ts-ignore
|
||||
const bundleService = (await import("./bundle.js")).default as any;
|
||||
// TODO: Remove after porting the file
|
||||
// @ts-ignore
|
||||
const froca = (await import("./froca.js")).default as any;
|
||||
const originEntity = message.originEntityId ? await froca.getNote(message.originEntityId) : null;
|
||||
|
||||
bundleService.getAndExecuteBundle(message.currentNoteId, originEntity, message.script, message.params);
|
||||
@@ -157,7 +161,7 @@ function waitForEntityChangeId(desiredEntityChangeId: number) {
|
||||
|
||||
return new Promise<void>((res, rej) => {
|
||||
entityChangeIdReachedListeners.push({
|
||||
desiredEntityChangeId,
|
||||
desiredEntityChangeId: desiredEntityChangeId,
|
||||
resolvePromise: res,
|
||||
start: Date.now()
|
||||
});
|
||||
@@ -201,7 +205,7 @@ async function consumeFrontendUpdateData() {
|
||||
} else {
|
||||
console.log("nonProcessedEntityChanges causing the timeout", nonProcessedEntityChanges);
|
||||
|
||||
toast.showError(t("ws.encountered-error", { message: e.message }));
|
||||
toastService.showError(t("ws.encountered-error", { message: e.message }));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,107 +1,66 @@
|
||||
import "jquery";
|
||||
|
||||
import utils from "./services/utils.js";
|
||||
import ko from "knockout";
|
||||
|
||||
type SetupStep = "sync-in-progress" | "setup-type" | "new-document-in-progress" | "sync-from-desktop" | "sync-from-server";
|
||||
type SetupType = "new-document" | "sync-from-desktop" | "sync-from-server" | "";
|
||||
// TriliumNextTODO: properly make use of below types
|
||||
// type SetupModelSetupType = "new-document" | "sync-from-desktop" | "sync-from-server" | "";
|
||||
// type SetupModelStep = "sync-in-progress" | "setup-type" | "new-document-in-progress" | "sync-from-desktop";
|
||||
|
||||
class SetupController {
|
||||
private step: SetupStep;
|
||||
private setupType: SetupType = "";
|
||||
private syncPollIntervalId: number | null = null;
|
||||
private rootNode: HTMLElement;
|
||||
private setupTypeForm: HTMLFormElement;
|
||||
private syncFromServerForm: HTMLFormElement;
|
||||
private setupTypeNextButton: HTMLButtonElement;
|
||||
private setupTypeInputs: HTMLInputElement[];
|
||||
private syncServerHostInput: HTMLInputElement;
|
||||
private syncProxyInput: HTMLInputElement;
|
||||
private passwordInput: HTMLInputElement;
|
||||
private sections: Record<SetupStep, HTMLElement>;
|
||||
class SetupModel {
|
||||
syncInProgress: boolean;
|
||||
step: ko.Observable<string>;
|
||||
setupType: ko.Observable<string>;
|
||||
setupNewDocument: ko.Observable<boolean>;
|
||||
setupSyncFromDesktop: ko.Observable<boolean>;
|
||||
setupSyncFromServer: ko.Observable<boolean>;
|
||||
syncServerHost: ko.Observable<string | undefined>;
|
||||
syncProxy: ko.Observable<string | undefined>;
|
||||
password: ko.Observable<string | undefined>;
|
||||
|
||||
constructor(rootNode: HTMLElement, syncInProgress: boolean) {
|
||||
this.rootNode = rootNode;
|
||||
this.step = syncInProgress ? "sync-in-progress" : "setup-type";
|
||||
this.setupTypeForm = mustGetElement("setup-type-form", HTMLFormElement);
|
||||
this.syncFromServerForm = mustGetElement("sync-from-server-form", HTMLFormElement);
|
||||
this.setupTypeNextButton = mustGetElement("setup-type-next", HTMLButtonElement);
|
||||
this.setupTypeInputs = Array.from(document.querySelectorAll<HTMLInputElement>("input[name='setup-type']"));
|
||||
this.syncServerHostInput = mustGetElement("sync-server-host", HTMLInputElement);
|
||||
this.syncProxyInput = mustGetElement("sync-proxy", HTMLInputElement);
|
||||
this.passwordInput = mustGetElement("password", HTMLInputElement);
|
||||
this.sections = {
|
||||
"setup-type": mustGetElement("setup-type-section", HTMLElement),
|
||||
"new-document-in-progress": mustGetElement("new-document-in-progress-section", HTMLElement),
|
||||
"sync-from-desktop": mustGetElement("sync-from-desktop-section", HTMLElement),
|
||||
"sync-from-server": mustGetElement("sync-from-server-section", HTMLElement),
|
||||
"sync-in-progress": mustGetElement("sync-in-progress-section", HTMLElement)
|
||||
};
|
||||
}
|
||||
constructor(syncInProgress: boolean) {
|
||||
this.syncInProgress = syncInProgress;
|
||||
this.step = ko.observable(syncInProgress ? "sync-in-progress" : "setup-type");
|
||||
this.setupType = ko.observable("");
|
||||
this.setupNewDocument = ko.observable(false);
|
||||
this.setupSyncFromDesktop = ko.observable(false);
|
||||
this.setupSyncFromServer = ko.observable(false);
|
||||
this.syncServerHost = ko.observable();
|
||||
this.syncProxy = ko.observable();
|
||||
this.password = ko.observable();
|
||||
|
||||
init() {
|
||||
this.setupTypeForm.addEventListener("submit", (event) => {
|
||||
event.preventDefault();
|
||||
void this.selectSetupType();
|
||||
});
|
||||
|
||||
this.syncFromServerForm.addEventListener("submit", (event) => {
|
||||
event.preventDefault();
|
||||
void this.finish();
|
||||
});
|
||||
|
||||
for (const input of this.setupTypeInputs) {
|
||||
input.addEventListener("change", () => {
|
||||
this.setupType = input.value as SetupType;
|
||||
this.render();
|
||||
});
|
||||
if (this.syncInProgress) {
|
||||
setInterval(checkOutstandingSyncs, 1000);
|
||||
}
|
||||
|
||||
for (const backButton of document.querySelectorAll<HTMLElement>("[data-action='back']")) {
|
||||
backButton.addEventListener("click", () => {
|
||||
this.back();
|
||||
});
|
||||
}
|
||||
|
||||
const serverAddress = `${location.protocol}//${location.host}`;
|
||||
$("#current-host").html(serverAddress);
|
||||
|
||||
if (this.step === "sync-in-progress") {
|
||||
this.startSyncPolling();
|
||||
}
|
||||
|
||||
this.render();
|
||||
this.rootNode.style.display = "";
|
||||
}
|
||||
|
||||
private async selectSetupType() {
|
||||
if (this.setupType === "new-document") {
|
||||
this.setStep("new-document-in-progress");
|
||||
// this is called in setup.ejs
|
||||
setupTypeSelected() {
|
||||
return !!this.setupType();
|
||||
}
|
||||
|
||||
await $.post("api/setup/new-document");
|
||||
window.location.replace("./setup");
|
||||
return;
|
||||
}
|
||||
selectSetupType() {
|
||||
if (this.setupType() === "new-document") {
|
||||
this.step("new-document-in-progress");
|
||||
|
||||
if (this.setupType) {
|
||||
this.setStep(this.setupType);
|
||||
$.post("api/setup/new-document").then(() => {
|
||||
window.location.replace("./setup");
|
||||
});
|
||||
} else {
|
||||
this.step(this.setupType());
|
||||
}
|
||||
}
|
||||
|
||||
private back() {
|
||||
this.setStep("setup-type");
|
||||
this.setupType = "";
|
||||
|
||||
for (const input of this.setupTypeInputs) {
|
||||
input.checked = false;
|
||||
}
|
||||
|
||||
this.render();
|
||||
back() {
|
||||
this.step("setup-type");
|
||||
this.setupType("");
|
||||
}
|
||||
|
||||
private async finish() {
|
||||
const syncServerHost = this.syncServerHostInput.value.trim().replace(/\/+$/, "");
|
||||
const syncProxy = this.syncProxyInput.value.trim();
|
||||
const password = this.passwordInput.value;
|
||||
async finish() {
|
||||
const syncServerHost = this.syncServerHost();
|
||||
const syncProxy = this.syncProxy();
|
||||
const password = this.password();
|
||||
|
||||
if (!syncServerHost) {
|
||||
showAlert("Trilium server address can't be empty");
|
||||
@@ -115,44 +74,21 @@ class SetupController {
|
||||
|
||||
// not using server.js because it loads too many dependencies
|
||||
const resp = await $.post("api/setup/sync-from-server", {
|
||||
syncServerHost,
|
||||
syncProxy,
|
||||
password
|
||||
syncServerHost: syncServerHost,
|
||||
syncProxy: syncProxy,
|
||||
password: password
|
||||
});
|
||||
|
||||
if (resp.result === "success") {
|
||||
this.step("sync-in-progress");
|
||||
|
||||
setInterval(checkOutstandingSyncs, 1000);
|
||||
|
||||
hideAlert();
|
||||
this.setStep("sync-in-progress");
|
||||
this.startSyncPolling();
|
||||
} else {
|
||||
showAlert(`Sync setup failed: ${resp.error}`);
|
||||
}
|
||||
}
|
||||
|
||||
private setStep(step: SetupStep) {
|
||||
this.step = step;
|
||||
this.render();
|
||||
}
|
||||
|
||||
private render() {
|
||||
for (const [step, section] of Object.entries(this.sections) as [SetupStep, HTMLElement][]) {
|
||||
section.style.display = step === this.step ? "" : "none";
|
||||
}
|
||||
|
||||
this.setupTypeNextButton.disabled = !this.setupType;
|
||||
}
|
||||
|
||||
private getSelectedSetupType(): SetupType {
|
||||
return (this.setupTypeInputs.find((input) => input.checked)?.value ?? "") as SetupType;
|
||||
}
|
||||
|
||||
private startSyncPolling() {
|
||||
if (this.syncPollIntervalId !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.syncPollIntervalId = window.setInterval(checkOutstandingSyncs, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
async function checkOutstandingSyncs() {
|
||||
@@ -186,19 +122,7 @@ function getSyncInProgress() {
|
||||
return !!parseInt(el.content);
|
||||
}
|
||||
|
||||
function mustGetElement<T extends typeof HTMLElement>(id: string, ctor: T): InstanceType<T> {
|
||||
const element = document.getElementById(id);
|
||||
|
||||
if (!element || !(element instanceof ctor)) {
|
||||
throw new Error(`Expected element #${id}`);
|
||||
}
|
||||
|
||||
return element as InstanceType<T>;
|
||||
}
|
||||
|
||||
addEventListener("DOMContentLoaded", (event) => {
|
||||
const rootNode = document.getElementById("setup-dialog");
|
||||
if (!rootNode || !(rootNode instanceof HTMLElement)) return;
|
||||
|
||||
new SetupController(rootNode, getSyncInProgress()).init();
|
||||
ko.applyBindings(new SetupModel(getSyncInProgress()), document.getElementById("setup-dialog"));
|
||||
$("#setup-dialog").show();
|
||||
});
|
||||
|
||||
@@ -1230,43 +1230,6 @@ a.external:not(.no-arrow):after, a[href^="http://"]:not(.no-arrow):after, a[href
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Expandable include note styles */
|
||||
.include-note-title-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.include-note-title-row .include-note-title {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.include-note-toggle {
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 2px;
|
||||
cursor: pointer;
|
||||
font-size: 1.2em;
|
||||
color: var(--main-text-color);
|
||||
transition: transform 0.2s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.include-note-toggle:hover {
|
||||
color: var(--main-link-color);
|
||||
}
|
||||
|
||||
.include-note-toggle.expanded {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.include-note[data-box-size="expandable"] .include-note-content {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.alert {
|
||||
padding: 8px 14px;
|
||||
width: auto;
|
||||
@@ -1649,7 +1612,11 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
|
||||
}
|
||||
|
||||
body.mobile #launcher-container {
|
||||
justify-content: space-evenly;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
body.mobile #launcher-container button {
|
||||
margin: 0 16px;
|
||||
}
|
||||
|
||||
body.mobile .modal.show {
|
||||
@@ -1787,11 +1754,8 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
|
||||
justify-content: space-between;
|
||||
align-items: baseline;
|
||||
font-weight: bold;
|
||||
color: var(--muted-text-color) !important;
|
||||
}
|
||||
|
||||
#right-pane .card-header-title {
|
||||
text-transform: uppercase;
|
||||
color: var(--muted-text-color) !important;
|
||||
}
|
||||
|
||||
#right-pane .card-header-buttons {
|
||||
@@ -2678,26 +2642,3 @@ iframe.print-iframe {
|
||||
min-height: 50px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.ocr-text-section {
|
||||
padding: 10px;
|
||||
background: var(--accented-background-color);
|
||||
border-left: 3px solid var(--main-border-color);
|
||||
text-align: left;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ocr-header {
|
||||
font-weight: bold;
|
||||
margin-bottom: 8px;
|
||||
font-size: 0.9em;
|
||||
color: var(--muted-text-color);
|
||||
}
|
||||
|
||||
.ocr-content {
|
||||
max-height: 150px;
|
||||
overflow-y: auto;
|
||||
font-size: 0.9em;
|
||||
line-height: 1.4;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
11
apps/client/src/stylesheets/theme-next.css
Normal file
11
apps/client/src/stylesheets/theme-next.css
Normal file
@@ -0,0 +1,11 @@
|
||||
/* Import the light color scheme.
|
||||
* This is the base color scheme, always active and overridden by the dark
|
||||
* color scheme stylesheet when necessary. */
|
||||
@import url(./theme-next-light.css);
|
||||
|
||||
/* Import the dark color scheme when the system preference is set to dark mode */
|
||||
@import url(./theme-next-dark.css) (prefers-color-scheme: dark);
|
||||
|
||||
:root {
|
||||
--theme-style-auto: true;
|
||||
}
|
||||
@@ -544,11 +544,14 @@ li.dropdown-item a.dropdown-item-button:focus-visible {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#toast-container .toast .toast-header .btn-close,
|
||||
#toast-container .toast .toast-close .btn-close {
|
||||
#toast-container .toast .toast-header .btn-close {
|
||||
margin: 0 0 0 12px;
|
||||
}
|
||||
|
||||
#toast-container .toast.no-title {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
#toast-container .toast .toast-body {
|
||||
flex-grow: 1;
|
||||
overflow: hidden;
|
||||
@@ -672,11 +675,10 @@ li.dropdown-item a.dropdown-item-button:focus-visible {
|
||||
div.alert {
|
||||
margin-bottom: 8px;
|
||||
background: var(--alert-bar-background) !important;
|
||||
color: var(--main-text-color);
|
||||
border-radius: 8px;
|
||||
font-size: .85em;
|
||||
}
|
||||
|
||||
div.alert p + p {
|
||||
margin-block: 1em 0;
|
||||
}
|
||||
}
|
||||
@@ -26,8 +26,7 @@
|
||||
.modal .modal-header .btn-close,
|
||||
.modal .modal-header .help-button,
|
||||
.modal .modal-header .custom-title-bar-button,
|
||||
#toast-container .toast .toast-header .btn-close,
|
||||
#toast-container .toast .toast-close .btn-close {
|
||||
#toast-container .toast .toast-header .btn-close {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
@@ -47,14 +46,12 @@
|
||||
}
|
||||
|
||||
.modal .modal-header .btn-close,
|
||||
#toast-container .toast .toast-header .btn-close,
|
||||
#toast-container .toast .toast-close .btn-close {
|
||||
#toast-container .toast .toast-header .btn-close {
|
||||
--modal-control-button-hover-background: var(--modal-close-button-hover-background);
|
||||
}
|
||||
|
||||
.modal .modal-header .btn-close::after,
|
||||
#toast-container .toast .toast-header .btn-close::after,
|
||||
#toast-container .toast .toast-close .btn-close::after {
|
||||
#toast-container .toast .toast-header .btn-close::after {
|
||||
content: "\ec8d";
|
||||
font-family: boxicons;
|
||||
}
|
||||
@@ -70,8 +67,7 @@
|
||||
.modal .modal-header .btn-close:hover,
|
||||
.modal .modal-header .help-button:hover,
|
||||
.modal .modal-header .custom-title-bar-button:hover,
|
||||
#toast-container .toast .toast-header .btn-close:hover,
|
||||
#toast-container .toast .toast-close .btn-close:hover {
|
||||
#toast-container .toast .toast-header .btn-close:hover {
|
||||
background: var(--modal-control-button-hover-background);
|
||||
color: var(--modal-control-button-hover-color);
|
||||
}
|
||||
@@ -79,22 +75,19 @@
|
||||
.modal .modal-header .btn-close:active,
|
||||
.modal .modal-header .help-button:active,
|
||||
.modal .modal-header .custom-title-bar-button:active,
|
||||
#toast-container .toast .toast-header .btn-close:active,
|
||||
#toast-container .toast .toast-close .btn-close:active {
|
||||
#toast-container .toast .toast-header .btn-close:active {
|
||||
transform: scale(.85);
|
||||
}
|
||||
|
||||
.modal .modal-header .btn-close:focus,
|
||||
.modal .modal-header .help-button:focus,
|
||||
#toast-container .toast .toast-header .btn-close:focus,
|
||||
#toast-container .toast .toast-close .btn-close:focus {
|
||||
#toast-container .toast .toast-header .btn-close:focus {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.modal .modal-header .btn-close:focus-visible,
|
||||
.modal .modal-header .help-button:focus-visible,
|
||||
#toast-container .toast .toast-header .btn-close:focus-visible,
|
||||
#toast-container .toast .toast-close .btn-close:focus-visible {
|
||||
#toast-container .toast .toast-header .btn-close:focus-visible {
|
||||
outline: 2px solid var(--input-focus-outline-color);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
11
apps/client/src/stylesheets/theme.css
Normal file
11
apps/client/src/stylesheets/theme.css
Normal file
@@ -0,0 +1,11 @@
|
||||
/* Import the light color scheme.
|
||||
* This is the base color scheme, always active and overridden by the dark
|
||||
* color scheme stylesheet when necessary. */
|
||||
@import url(./theme-light.css);
|
||||
|
||||
/* Import the dark color scheme when the system preference is set to dark mode */
|
||||
@import url(./theme-dark.css) (prefers-color-scheme: dark);
|
||||
|
||||
:root {
|
||||
--theme-style-auto: true;
|
||||
}
|
||||
@@ -393,7 +393,9 @@
|
||||
},
|
||||
"delete_notes": {
|
||||
"close": "غلق",
|
||||
"cancel": "الغاء"
|
||||
"cancel": "الغاء",
|
||||
"ok": "نعم",
|
||||
"delete_notes_preview": "حذف معاينة الملاحظات"
|
||||
},
|
||||
"export": {
|
||||
"close": "غلق",
|
||||
@@ -624,8 +626,7 @@
|
||||
"date-and-time": "التاريخ والوقت",
|
||||
"no_backup_yet": "لايوجد نسخة احتياطية لحد الان",
|
||||
"enable_daily_backup": "تمكين النسخ الاحتياطي اليومي",
|
||||
"backup_database_now": "نسخ اختياطي لقاعدة البيانات الان",
|
||||
"download": "تنزيل"
|
||||
"backup_database_now": "نسخ اختياطي لقاعدة البيانات الان"
|
||||
},
|
||||
"etapi": {
|
||||
"created": "تم الأنشاء",
|
||||
@@ -662,6 +663,7 @@
|
||||
"default_shortcuts": "اختصارات افتراضية"
|
||||
},
|
||||
"sync_2": {
|
||||
"timeout_unit": "ميلي ثانية",
|
||||
"note": "ملاحظة",
|
||||
"save": "حفظ",
|
||||
"help": "المساعدة",
|
||||
@@ -1067,6 +1069,7 @@
|
||||
"rename_note": "اعادة تسمية الملاحظة",
|
||||
"remove_relation": "حذف العلاقة",
|
||||
"default_new_note_title": "ملاحظة جديدة",
|
||||
"open_in_new_tab": "فتح في تبويب جديد",
|
||||
"enter_new_title": "ادخل عنوان ملاحظة جديدة:",
|
||||
"note_not_found": "الملاحظة {{noteId}} غير موجودة!",
|
||||
"cannot_match_transform": "تعذر مطابقة التحويل: {{transform}}"
|
||||
@@ -1127,7 +1130,9 @@
|
||||
"spellcheck": {
|
||||
"title": "التدقيق الاملائي",
|
||||
"enable": "تفعيل التدقيق الاملائي",
|
||||
"language_code_label": "رمز اللغة او رموز اللغات"
|
||||
"language_code_label": "رمز اللغة او رموز اللغات",
|
||||
"available_language_codes_label": "رموز اللغات المتاحة:",
|
||||
"language_code_placeholder": "على سبيل المثال \"en-US\", \"de-AI\""
|
||||
},
|
||||
"note-map": {
|
||||
"button-link-map": "خريطة الروابط",
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
},
|
||||
"delete_notes": {
|
||||
"close": "Tanca",
|
||||
"cancel": "Cancel·la"
|
||||
"cancel": "Cancel·la",
|
||||
"ok": "OK"
|
||||
},
|
||||
"export": {
|
||||
"close": "Tanca",
|
||||
@@ -92,10 +93,7 @@
|
||||
"digits": "dígits",
|
||||
"inheritable": "Heretable",
|
||||
"delete": "Suprimeix",
|
||||
"color_type": "Color",
|
||||
"textarea": "Text multi linia",
|
||||
"date_time": "Data i hora",
|
||||
"precision_title": "Quants dígits han d'estar disponibles per a coma flotant a la interfície de configuració."
|
||||
"color_type": "Color"
|
||||
},
|
||||
"rename_label": {
|
||||
"to": "Per"
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
"also_delete_note": "同时删除笔记"
|
||||
},
|
||||
"delete_notes": {
|
||||
"delete_notes_preview": "删除笔记预览",
|
||||
"close": "关闭",
|
||||
"delete_all_clones_description": "同时删除所有克隆(可以在最近修改中撤消)",
|
||||
"erase_notes_description": "通常(软)删除仅标记笔记为已删除,可以在一段时间内通过最近修改对话框撤消。选中此选项将立即擦除笔记,不可撤销。",
|
||||
@@ -95,7 +96,9 @@
|
||||
"notes_to_be_deleted": "将删除以下笔记 ({{notesCount}})",
|
||||
"no_note_to_delete": "没有笔记将被删除(仅克隆)。",
|
||||
"broken_relations_to_be_deleted": "将删除以下关系并断开连接 ({{ relationCount}})",
|
||||
"cancel": "取消"
|
||||
"cancel": "取消",
|
||||
"ok": "确定",
|
||||
"deleted_relation_text": "笔记 {{- note}} (将被删除的笔记) 被以下关系 {{- relation}} 引用, 来自 {{- source}}。"
|
||||
},
|
||||
"export": {
|
||||
"export_note_title": "导出笔记",
|
||||
@@ -365,7 +368,7 @@
|
||||
"calendar_root": "标记应用作为每日笔记的根。只应标记一个笔记。",
|
||||
"archived": "含有此标签的笔记默认在搜索结果中不可见(也适用于跳转到、添加链接对话框等)。",
|
||||
"exclude_from_export": "笔记(及其子树)不会包含在任何笔记导出中",
|
||||
"run": "定义脚本应运行的事件。可能的值包括:\n<ul>\n<li>frontendStartup - Trilium前端启动时(或刷新时),但不会在移动端执行。</li>\n<li>mobileStartup - Trilium前端启动时(或刷新时), 在移动端会执行。</li>\n<li>backendStartup - Trilium后端启动时。</li>\n<li>hourly - 每小时运行一次。您可以使用附加标签<code>runAtHour</code>指定小时。</li>\n<li>daily - 每天运行一次。</li>\n</ul>",
|
||||
"run": "定义脚本应运行的事件。可能的值包括:\n<ul>\n<li>frontendStartup - Trilium前端启动时(或刷新时),但不会在移动端执行。</li>\n<li>mobileStartup - Trilium前端启动时(或刷新时), 在移动端会执行。</li>\n<li>backendStartup - Trilium后端启动时</li>\n<li>hourly - 每小时运行一次。您可以使用附加标签<code>runAtHour</code>指定小时。</li>\n<li>daily - 每天运行一次</li>\n</ul>",
|
||||
"run_on_instance": "定义应在哪个Trilium实例上运行。默认为所有实例。",
|
||||
"run_at_hour": "应在哪个小时运行。应与<code>#run=hourly</code>一起使用。可以多次定义,以便一天内运行多次。",
|
||||
"disable_inclusion": "含有此标签的脚本不会包含在父脚本执行中。",
|
||||
@@ -443,8 +446,7 @@
|
||||
"and_more": "... 以及另外 {{count}} 个。",
|
||||
"print_landscape": "导出为 PDF 时,将页面方向更改为横向而不是纵向。",
|
||||
"print_page_size": "导出为 PDF 时,更改页面大小。支持的值:<code>A0</code>、<code>A1</code>、<code>A2</code>、<code>A3</code>、<code>A4</code>、<code>A5</code>、<code>A6</code>、<code>Legal</code>、<code>Letter</code>、<code>Tabloid</code>、<code>Ledger</code>。",
|
||||
"color_type": "颜色",
|
||||
"textarea": "多行文本"
|
||||
"color_type": "颜色"
|
||||
},
|
||||
"attribute_editor": {
|
||||
"help_text_body1": "要添加标签,只需输入例如 <code>#rock</code> 或者如果您还想添加值,则例如 <code>#year = 2020</code>",
|
||||
@@ -706,8 +708,7 @@
|
||||
"advanced": "高级",
|
||||
"export_as_image": "导出为图像",
|
||||
"export_as_image_png": "PNG(栅格)",
|
||||
"export_as_image_svg": "SVG(矢量图)",
|
||||
"view_ocr_text": "查看 OCR 文本"
|
||||
"export_as_image_svg": "SVG(矢量图)"
|
||||
},
|
||||
"onclick_button": {
|
||||
"no_click_handler": "按钮组件'{{componentId}}'没有定义点击处理程序"
|
||||
@@ -801,10 +802,7 @@
|
||||
"expand_first_level": "展开直接子代",
|
||||
"expand_nth_level": "展开 {{depth}} 层",
|
||||
"expand_all_levels": "展开所有层级",
|
||||
"hide_child_notes": "隐藏树中的子笔记",
|
||||
"open_all_in_tabs": "全部打开",
|
||||
"open_all_in_tabs_tooltip": "在新标签页中打开所有结果",
|
||||
"open_all_confirm": "这将在新标签页中打开 {{count}} 个笔记。继续吗?"
|
||||
"hide_child_notes": "隐藏树中的子笔记"
|
||||
},
|
||||
"edited_notes": {
|
||||
"no_edited_notes_found": "今天还没有编辑过的笔记...",
|
||||
@@ -858,8 +856,7 @@
|
||||
"collapse": "折叠到正常大小",
|
||||
"title": "笔记地图",
|
||||
"fix-nodes": "固定节点",
|
||||
"link-distance": "链接距离",
|
||||
"too-many-notes": "此子树包含 {{count}} 个笔记,超过了笔记地图中可显示的 {{max}} 个笔记的限制。"
|
||||
"link-distance": "链接距离"
|
||||
},
|
||||
"note_paths": {
|
||||
"title": "笔记路径",
|
||||
@@ -1050,6 +1047,7 @@
|
||||
"unprotecting-title": "解除保护状态"
|
||||
},
|
||||
"relation_map": {
|
||||
"open_in_new_tab": "在新标签页中打开",
|
||||
"remove_note": "删除笔记",
|
||||
"edit_title": "编辑标题",
|
||||
"rename_note": "重命名笔记",
|
||||
@@ -1064,8 +1062,7 @@
|
||||
"note_already_in_diagram": "笔记 \"{{title}}\" 已经在图中。",
|
||||
"enter_title_of_new_note": "输入新笔记的标题",
|
||||
"default_new_note_title": "新笔记",
|
||||
"click_on_canvas_to_place_new_note": "点击画布以放置新笔记",
|
||||
"rename_relation": "重命名关系"
|
||||
"click_on_canvas_to_place_new_note": "点击画布以放置新笔记"
|
||||
},
|
||||
"backend_log": {
|
||||
"refresh": "刷新"
|
||||
@@ -1200,28 +1197,12 @@
|
||||
},
|
||||
"images": {
|
||||
"images_section_title": "图片",
|
||||
"download_images_automatically": "自动下载图片",
|
||||
"download_images_description": "从粘贴的 HTML 代码中下载引用的在线图片,以便离线使用。",
|
||||
"enable_image_compression": "图片压缩",
|
||||
"max_image_dimensions": "最大图像尺寸",
|
||||
"jpeg_quality_description": "建议范围为 50–85。较低的值可以减小文件大小,较高的值可以保留细节。",
|
||||
"max_image_dimensions_unit": "像素",
|
||||
"enable_image_compression_description": "上传或粘贴图片时,对其进行压缩和调整大小。",
|
||||
"max_image_dimensions_description": "超过此尺寸的图片将自动调整大小。",
|
||||
"jpeg_quality": "JPEG质量",
|
||||
"ocr_section_title": "文本提取(OCR)",
|
||||
"ocr_related_content_languages": "内容语言(用于文本提取)",
|
||||
"ocr_auto_process": "自动处理新文件",
|
||||
"ocr_auto_process_description": "自动从新上传或粘贴的文件中提取文本。",
|
||||
"ocr_min_confidence": "最低置信度",
|
||||
"ocr_confidence_description": "仅提取置信度高于此阈值的文本。较低的置信度阈值会包含更多文本,但可能准确性较低。",
|
||||
"batch_ocr_title": "处理现有文件",
|
||||
"batch_ocr_description": "从笔记中的所有现有图像、PDF 和 Office 文档中提取文本。这可能需要一些时间,具体取决于文件数量。",
|
||||
"batch_ocr_start": "开始批量处理",
|
||||
"batch_ocr_starting": "开始批量处理...",
|
||||
"batch_ocr_progress": "正在处理 {{processed}} 个文件,共 {{total}} 个文件...",
|
||||
"batch_ocr_completed": "批量处理完成!已处理 {{processed}} 个文件。",
|
||||
"batch_ocr_error": "批量处理过程中出错:{{error}}"
|
||||
"download_images_automatically": "自动下载图片以供离线使用。",
|
||||
"download_images_description": "粘贴的 HTML 可能包含在线图片的引用,Trilium 会找到这些引用并下载图片,以便它们可以离线使用。",
|
||||
"enable_image_compression": "启用图片压缩",
|
||||
"max_image_dimensions": "图片的最大宽度/高度(超过此限制的图像将会被缩放)。",
|
||||
"jpeg_quality_description": "JPEG 质量(10 - 最差质量,100 最佳质量,建议为 50 - 85)",
|
||||
"max_image_dimensions_unit": "像素"
|
||||
},
|
||||
"attachment_erasure_timeout": {
|
||||
"attachment_erasure_timeout": "附件清理超时",
|
||||
@@ -1339,8 +1320,7 @@
|
||||
"date-and-time": "日期和时间",
|
||||
"path": "路径",
|
||||
"database_backed_up_to": "数据库已备份到 {{backupFilePath}}",
|
||||
"no_backup_yet": "尚无备份",
|
||||
"download": "下载"
|
||||
"no_backup_yet": "尚无备份"
|
||||
},
|
||||
"etapi": {
|
||||
"title": "ETAPI",
|
||||
@@ -1438,15 +1418,12 @@
|
||||
"spellcheck": {
|
||||
"title": "拼写检查",
|
||||
"description": "这些选项仅适用于桌面版本,浏览器将使用其原生的拼写检查功能。",
|
||||
"enable": "拼写检查",
|
||||
"language_code_label": "拼写检查语言",
|
||||
"restart-required": "拼写检查选项的更改将在应用重启后生效。",
|
||||
"custom_dictionary_title": "自定义词典",
|
||||
"custom_dictionary_description": "添加到词典中的单词会在您的所有设备上同步。",
|
||||
"custom_dictionary_edit": "自定义词",
|
||||
"custom_dictionary_edit_description": "编辑拼写检查器不应标记的单词列表。更改将在重启后生效。",
|
||||
"custom_dictionary_open": "编辑词典",
|
||||
"related_description": "配置拼写检查语言和自定义词典。"
|
||||
"enable": "启用拼写检查",
|
||||
"language_code_label": "语言代码",
|
||||
"language_code_placeholder": "例如 \"en-US\", \"de-AT\"",
|
||||
"multiple_languages_info": "多种语言可以用逗号分隔,例如 \"en-US, de-DE, cs\"。 ",
|
||||
"available_language_codes_label": "可用的语言代码:",
|
||||
"restart-required": "拼写检查选项的更改将在应用重启后生效。"
|
||||
},
|
||||
"sync_2": {
|
||||
"config_title": "同步配置",
|
||||
@@ -1462,7 +1439,7 @@
|
||||
"test_description": "测试和同步服务器之间的连接。如果同步服务器没有初始化,会将本地文档同步到同步服务器上。",
|
||||
"test_button": "测试同步",
|
||||
"handshake_failed": "同步服务器握手失败,错误:{{message}}",
|
||||
"timeout_description": "同步连接速度慢时,应该等待多久才放弃?如果网络不稳定,请增加等待时间。"
|
||||
"timeout_unit": "毫秒"
|
||||
},
|
||||
"api_log": {
|
||||
"close": "关闭"
|
||||
@@ -1558,9 +1535,8 @@
|
||||
"new-feature": "新建",
|
||||
"collections": "集合",
|
||||
"book": "集合",
|
||||
"ai-chat": "AI对话",
|
||||
"spreadsheet": "电子表格",
|
||||
"llm-chat": "AI对话"
|
||||
"ai-chat": "AI聊天",
|
||||
"spreadsheet": "电子表格"
|
||||
},
|
||||
"protect_note": {
|
||||
"toggle-on": "保护笔记",
|
||||
@@ -1885,7 +1861,7 @@
|
||||
},
|
||||
"content_language": {
|
||||
"title": "内容语言",
|
||||
"description": "在只读或可编辑文本笔记的“基本属性”部分,选择一种或多种语言,这些语言将显示在语言选择列表中。这将启用拼写检查、从右到左的阅读支持和文本提取(OCR)等功能。"
|
||||
"description": "选择一种或多种语言出现在只读或可编辑文本注释的基本属性,这将支持拼写检查或从右向左之类的功能。"
|
||||
},
|
||||
"switch_layout_button": {
|
||||
"title_vertical": "将编辑面板移至底部",
|
||||
@@ -2070,9 +2046,7 @@
|
||||
"title": "实验选项",
|
||||
"disclaimer": "这些选项处于实验阶段,可能导致系统不稳定。请谨慎使用。",
|
||||
"new_layout_name": "新布局",
|
||||
"new_layout_description": "尝试全新布局,呈现更现代的外观并提升易用性。后续版本将进行重大调整。",
|
||||
"llm_name": "AI/大语言模型对话",
|
||||
"llm_description": "启用由大语言模型驱动的 AI对话侧边栏和大语言模型对话笔记。"
|
||||
"new_layout_description": "尝试全新布局,呈现更现代的外观并提升易用性。后续版本将进行重大调整。"
|
||||
},
|
||||
"tab_history_navigation_buttons": {
|
||||
"go-back": "返回前一笔记",
|
||||
@@ -2194,137 +2168,5 @@
|
||||
},
|
||||
"setup_form": {
|
||||
"more_info": "了解更多"
|
||||
},
|
||||
"media": {
|
||||
"play": "播放(空格)",
|
||||
"pause": "暂停(空格)",
|
||||
"back-10s": "后退10秒(左箭头键)",
|
||||
"forward-30s": "前进30秒",
|
||||
"mute": "静音(M)",
|
||||
"unmute": "取消静音(M)",
|
||||
"playback-speed": "播放速度",
|
||||
"loop": "循环播放",
|
||||
"disable-loop": "禁用循环播放",
|
||||
"rotate": "旋转",
|
||||
"picture-in-picture": "画中画",
|
||||
"exit-picture-in-picture": "退出画中画",
|
||||
"fullscreen": "全屏(F)",
|
||||
"exit-fullscreen": "退出全屏",
|
||||
"unsupported-format": "此文件格式不支持媒体预览:\n{{mime}}",
|
||||
"zoom-to-fit": "缩放以填充",
|
||||
"zoom-reset": "重置缩放以填充"
|
||||
},
|
||||
"mermaid": {
|
||||
"sample_diagrams": "示例图:",
|
||||
"sample_flowchart": "流程图",
|
||||
"sample_class": "类图",
|
||||
"sample_sequence": "时序图",
|
||||
"sample_entity_relationship": "实体关系图",
|
||||
"sample_state": "状态图",
|
||||
"sample_mindmap": "思维导图",
|
||||
"sample_architecture": "架构图",
|
||||
"sample_block": "模块图",
|
||||
"sample_c4": "C4 图",
|
||||
"sample_gantt": "甘特图",
|
||||
"sample_git": "Git 流程图",
|
||||
"sample_kanban": "看板图",
|
||||
"sample_packet": "数据包图",
|
||||
"sample_pie": "饼图",
|
||||
"sample_quadrant": "象限图",
|
||||
"sample_radar": "雷达图",
|
||||
"sample_requirement": "需求图",
|
||||
"sample_sankey": "桑基图",
|
||||
"sample_timeline": "时间轴图",
|
||||
"sample_treemap": "树形图",
|
||||
"sample_user_journey": "用户旅程图",
|
||||
"sample_xy": "散点图",
|
||||
"sample_venn": "韦恩图",
|
||||
"sample_ishikawa": "鱼骨图",
|
||||
"placeholder": "输入你的美人鱼图的内容,或者使用下面的示例图之一。",
|
||||
"sample_treeview": "树形视图",
|
||||
"sample_wardley": "沃德利地图"
|
||||
},
|
||||
"llm_chat": {
|
||||
"placeholder": "输入消息…",
|
||||
"send": "发送",
|
||||
"sending": "正在发送...",
|
||||
"empty_state": "在下方输入消息,即可开始对话。",
|
||||
"searching_web": "在网上搜索…",
|
||||
"web_search": "联网搜索",
|
||||
"sources": "来源",
|
||||
"extended_thinking": "延伸思考",
|
||||
"legacy_models": "传统模型",
|
||||
"thinking": "正在思考...",
|
||||
"thought_process": "思考过程",
|
||||
"tool_calls": "{{count}} 次工具调用",
|
||||
"input": "输入",
|
||||
"result": "结果",
|
||||
"error": "错误",
|
||||
"tool_error": "失败",
|
||||
"total_tokens": "{{total}} 个词元",
|
||||
"tokens_detail": "{{prompt}} 提示词 + {{completion}} 补全",
|
||||
"tokens_used": "{{prompt}} 提示词 + {{completion}} 补全 = {{total}} 个词元",
|
||||
"tokens_used_with_cost": "{{prompt}} 提示词 + {{completion}} 补全 = {{total}} 个词元(约 ${{cost}})",
|
||||
"tokens_used_with_model": "{{model}}: {{prompt}} 提示词 + {{completion}} 补全 = {{total}} 个词元",
|
||||
"tokens_used_with_model_and_cost": "{{model}}: {{prompt}} 提示词 + {{completion}} 补全 = {{total}} 个词元(约 ${{cost}})",
|
||||
"tokens": "词元",
|
||||
"context_used": "{{percentage}}% 使用率",
|
||||
"note_context_enabled": "点击即可禁用笔记上下文:{{title}}",
|
||||
"note_context_disabled": "点击即可将当前注释添加到上下文中",
|
||||
"no_provider_message": "未配置人工智能提供商。添加一个即可开始对话。",
|
||||
"add_provider": "添加人工智能提供商",
|
||||
"note_tools": "笔记访问",
|
||||
"sources_summary": "来自 {{sites}} 个网站的 {{count}} 个来源"
|
||||
},
|
||||
"sidebar_chat": {
|
||||
"title": "AI对话",
|
||||
"launcher_title": "打开AI对话",
|
||||
"new_chat": "开始新对话",
|
||||
"save_chat": "将对话保存到笔记",
|
||||
"empty_state": "开始对话",
|
||||
"history": "对话历史",
|
||||
"recent_chats": "最近对话",
|
||||
"no_chats": "无历史对话"
|
||||
},
|
||||
"ocr": {
|
||||
"extracted_text": "提取文本(OCR)",
|
||||
"extracted_text_title": "提取文本(OCR)",
|
||||
"loading_text": "正在加载OCR文本...",
|
||||
"no_text_available": "暂无OCR文本",
|
||||
"no_text_explanation": "该笔记未进行 OCR 文本提取处理,或未找到文本。",
|
||||
"failed_to_load": "OCR文本加载失败",
|
||||
"process_now": "处理 OCR",
|
||||
"processing": "正在处理...",
|
||||
"processing_started": "OCR识别已开始。请稍候片刻并刷新页面。",
|
||||
"processing_failed": "OCR处理启动失败",
|
||||
"view_extracted_text": "查看提取的文本(OCR)",
|
||||
"processing_complete": "OCR识别处理完成。",
|
||||
"text_filtered_low_confidence": "OCR 检测到文本,置信度为 {{confidence}}% ,但由于您的最小阈值为 {{threshold}}% ,因此该文本已被丢弃。",
|
||||
"open_media_settings": "打开设置"
|
||||
},
|
||||
"mind-map": {
|
||||
"addChild": "添加子节点",
|
||||
"addParent": "添加父节点",
|
||||
"addSibling": "添加同级节点",
|
||||
"removeNode": "删除节点",
|
||||
"focus": "专注模式",
|
||||
"cancelFocus": "退出专注模式",
|
||||
"moveUp": "上移",
|
||||
"moveDown": "下移",
|
||||
"link": "链接",
|
||||
"linkBidirectional": "双向链接",
|
||||
"clickTips": "请点击目标节点",
|
||||
"summary": "总结"
|
||||
},
|
||||
"llm": {
|
||||
"settings_description": "配置人工智能和大语言模型集成。",
|
||||
"add_provider": "添加提供商",
|
||||
"settings_title": "AI / LLM",
|
||||
"feature_not_enabled": "在“设置”→“高级”→“实验性功能”中启用 LLM 实验性功能,即可使用 AI 集成。",
|
||||
"add_provider_title": "添加AI供应商",
|
||||
"configured_providers": "已配置的供应商",
|
||||
"no_providers_configured": "尚未配置任何供应商。",
|
||||
"provider_name": "名称",
|
||||
"provider_type": "供应商"
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -88,6 +88,7 @@
|
||||
"also_delete_note": "Auch die Notiz löschen"
|
||||
},
|
||||
"delete_notes": {
|
||||
"delete_notes_preview": "Vorschau der Notizen löschen",
|
||||
"close": "Schließen",
|
||||
"delete_all_clones_description": "auch alle Klone löschen (kann bei letzte Änderungen rückgängig gemacht werden)",
|
||||
"erase_notes_description": "Beim normalen (vorläufigen) Löschen werden die Notizen nur als gelöscht markiert und sie können innerhalb eines bestimmten Zeitraums (im Dialogfeld „Letzte Änderungen“) wiederhergestellt werden. Wenn du diese Option aktivierst, werden die Notizen sofort gelöscht und es ist nicht möglich, die Notizen wiederherzustellen.",
|
||||
@@ -95,7 +96,9 @@
|
||||
"notes_to_be_deleted": "Folgende Notizen werden gelöscht ({{notesCount}})",
|
||||
"no_note_to_delete": "Es werden keine Notizen gelöscht (nur Klone).",
|
||||
"broken_relations_to_be_deleted": "Folgende Beziehungen werden gelöst und gelöscht ({{ relationCount}})",
|
||||
"cancel": "Abbrechen"
|
||||
"cancel": "Abbrechen",
|
||||
"ok": "OK",
|
||||
"deleted_relation_text": "Notiz {{- note}} (soll gelöscht werden) wird von Beziehung {{- relation}} ausgehend von {{- source}} referenziert."
|
||||
},
|
||||
"export": {
|
||||
"export_note_title": "Notiz exportieren",
|
||||
@@ -443,8 +446,7 @@
|
||||
"and_more": "... und {{count}} mehr.",
|
||||
"print_landscape": "Beim Export als PDF, wird die Seitenausrichtung Querformat anstatt Hochformat verwendet.",
|
||||
"print_page_size": "Beim Export als PDF, wird die Größe der Seite angepasst. Unterstützte Größen: <code>A0</code>, <code>A1</code>, <code>A2</code>, <code>A3</code>, <code>A4</code>, <code>A5</code>, <code>A6</code>, <code>Legal</code>, <code>Letter</code>, <code>Tabloid</code>, <code>Ledger</code>.",
|
||||
"color_type": "Farbe",
|
||||
"textarea": "Mehrzeilen-Text"
|
||||
"color_type": "Farbe"
|
||||
},
|
||||
"attribute_editor": {
|
||||
"help_text_body1": "Um ein Label hinzuzufügen, gebe einfach z.B. ein. <code>#rock</code> oder wenn du auch einen Wert hinzufügen möchten, dann z.B. <code>#year = 2024</code>",
|
||||
@@ -1044,6 +1046,7 @@
|
||||
"unprotecting-title": "Ungeschützt-Status"
|
||||
},
|
||||
"relation_map": {
|
||||
"open_in_new_tab": "In neuem Tab öffnen",
|
||||
"remove_note": "Notiz entfernen",
|
||||
"edit_title": "Titel bearbeiten",
|
||||
"rename_note": "Notiz umbenennen",
|
||||
@@ -1383,6 +1386,9 @@
|
||||
"description": "Diese Optionen gelten nur für Desktop-Builds. Browser verwenden ihre eigene native Rechtschreibprüfung.",
|
||||
"enable": "Aktiviere die Rechtschreibprüfung",
|
||||
"language_code_label": "Sprachcode(s)",
|
||||
"language_code_placeholder": "zum Beispiel \"en-US\", \"de-AT\"",
|
||||
"multiple_languages_info": "Mehrere Sprachen können mit einem Komma getrennt werden z.B. \"en-US, de-DE, cs\". ",
|
||||
"available_language_codes_label": "Verfügbare Sprachcodes:",
|
||||
"restart-required": "Änderungen an den Rechtschreibprüfungsoptionen werden nach dem Neustart der Anwendung wirksam."
|
||||
},
|
||||
"sync_2": {
|
||||
@@ -1398,7 +1404,8 @@
|
||||
"test_title": "Synchronisierungstest",
|
||||
"test_description": "Dadurch werden die Verbindung und der Handshake zum Synchronisierungsserver getestet. Wenn der Synchronisierungsserver nicht initialisiert ist, wird er dadurch für die Synchronisierung mit dem lokalen Dokument eingerichtet.",
|
||||
"test_button": "Teste die Synchronisierung",
|
||||
"handshake_failed": "Handshake des Synchronisierungsservers fehlgeschlagen, Fehler: {{message}}"
|
||||
"handshake_failed": "Handshake des Synchronisierungsservers fehlgeschlagen, Fehler: {{message}}",
|
||||
"timeout_unit": "Millisekunden"
|
||||
},
|
||||
"api_log": {
|
||||
"close": "Schließen"
|
||||
@@ -2176,52 +2183,5 @@
|
||||
},
|
||||
"setup_form": {
|
||||
"more_info": "Mehr erfahren"
|
||||
},
|
||||
"media": {
|
||||
"play": "Abspielen (Arbeitsbereich)",
|
||||
"pause": "Pausieren (Arbeitsbereich)",
|
||||
"back-10s": "10 s zurück (Linke Pfeiltaste)",
|
||||
"forward-30s": "30 s vorwärts",
|
||||
"mute": "Stumm (M)",
|
||||
"unmute": "Stummschaltung aufheben (M)",
|
||||
"playback-speed": "Wiedergabegeschwindigkeit",
|
||||
"loop": "Schleife",
|
||||
"disable-loop": "Schleife deaktivieren",
|
||||
"rotate": "Rotieren",
|
||||
"picture-in-picture": "Bild-in-Bild",
|
||||
"exit-picture-in-picture": "Bild-in-Bild verlassen",
|
||||
"fullscreen": "Vollbild (F)",
|
||||
"exit-fullscreen": "Vollbild verlassen",
|
||||
"unsupported-format": "Medienvorschau ist für dieses Format nicht verfügbar:\n{{mime}}",
|
||||
"zoom-to-fit": "Zoomen um auszufüllen",
|
||||
"zoom-reset": "Zoomen um auszufüllen zurücksetzen"
|
||||
},
|
||||
"mermaid": {
|
||||
"placeholder": "Geben den Inhalt des Mermaid-Diagramms ein oder verwenden eine der folgenden Beispieldiagramme.",
|
||||
"sample_diagrams": "Beispieldiagramme:",
|
||||
"sample_flowchart": "Flussdiagramm",
|
||||
"sample_class": "Klasse",
|
||||
"sample_sequence": "Abfolge",
|
||||
"sample_entity_relationship": "Entität Beziehung",
|
||||
"sample_state": "Zustandsübergangsdiagramm",
|
||||
"sample_mindmap": "Mindmap",
|
||||
"sample_architecture": "Architektur",
|
||||
"sample_block": "Block",
|
||||
"sample_c4": "C4",
|
||||
"sample_gantt": "Gantt",
|
||||
"sample_git": "GitGraph",
|
||||
"sample_kanban": "Kanban",
|
||||
"sample_packet": "Paket",
|
||||
"sample_pie": "Kuchen",
|
||||
"sample_quadrant": "Quadrant",
|
||||
"sample_radar": "Radar",
|
||||
"sample_requirement": "Anforderung",
|
||||
"sample_sankey": "Sankey",
|
||||
"sample_timeline": "Zeitstrahl",
|
||||
"sample_treemap": "Kachel",
|
||||
"sample_user_journey": "Benutzererfahrung",
|
||||
"sample_xy": "XY",
|
||||
"sample_venn": "Mengen",
|
||||
"sample_ishikawa": "Ursache-Wirkung"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"about": {
|
||||
"title": "Σχετικά με το Trilium Notes",
|
||||
"title": "Πληροφορίες για το Trilium Notes",
|
||||
"homepage": "Αρχική Σελίδα:",
|
||||
"app_version": "Έκδοση εφαρμογής:",
|
||||
"db_version": "Έκδοση βάσης δεδομένων:",
|
||||
"sync_version": "Έκδοση συγχρονισμού:",
|
||||
"sync_version": "Έκδοση πρωτοκόλου συγχρονισμού:",
|
||||
"build_date": "Ημερομηνία χτισίματος εφαρμογής:",
|
||||
"build_revision": "Αριθμός αναθεώρησης χτισίματος:",
|
||||
"data_directory": "Φάκελος δεδομένων:"
|
||||
|
||||
@@ -88,23 +88,17 @@
|
||||
"also_delete_note": "Also delete the note"
|
||||
},
|
||||
"delete_notes": {
|
||||
"title": "Delete notes",
|
||||
"delete_notes_preview": "Delete notes preview",
|
||||
"close": "Close",
|
||||
"clones_label": "Clones",
|
||||
"delete_clones_description_one": "Also delete {{count}} other clone. Can be undone in recent changes.",
|
||||
"delete_clones_description_other": "Also delete {{count}} other clones. Can be undone in recent changes.",
|
||||
"delete_all_clones_description": "Delete also all clones (can be undone in recent changes)",
|
||||
"erase_notes_label": "Erase permanently",
|
||||
"erase_notes_description": "Erase notes immediately instead of soft deletion. This cannot be undone and will force application reload.",
|
||||
"erase_notes_description": "Normal (soft) deletion only marks the notes as deleted and they can be undeleted (in recent changes dialog) within a period of time. Checking this option will erase the notes immediately and it won't be possible to undelete the notes.",
|
||||
"erase_notes_warning": "Erase notes permanently (can't be undone), including all clones. This will force application reload.",
|
||||
"notes_to_be_deleted": "Notes to be deleted ({{notesCount}})",
|
||||
"notes_to_be_deleted": "Following notes will be deleted ({{notesCount}})",
|
||||
"no_note_to_delete": "No note will be deleted (only clones).",
|
||||
"broken_relations_to_be_deleted": "Broken relations ({{relationCount}})",
|
||||
"table_note_with_relation": "Note with relation",
|
||||
"table_relation": "Relation",
|
||||
"table_points_to": "Points to (deleted)",
|
||||
"broken_relations_to_be_deleted": "Following relations will be broken and deleted ({{ relationCount}})",
|
||||
"cancel": "Cancel",
|
||||
"delete": "Delete"
|
||||
"ok": "OK",
|
||||
"deleted_relation_text": "Note {{- note}} (to be deleted) is referenced by relation {{- relation}} originating from {{- source}}."
|
||||
},
|
||||
"export": {
|
||||
"export_note_title": "Export note",
|
||||
@@ -215,7 +209,6 @@
|
||||
"box_size_small": "small (~ 10 lines)",
|
||||
"box_size_medium": "medium (~ 30 lines)",
|
||||
"box_size_full": "full (box shows complete text)",
|
||||
"box_size_expandable": "expandable (collapsed by default)",
|
||||
"button_include": "Include note"
|
||||
},
|
||||
"info": {
|
||||
@@ -350,7 +343,6 @@
|
||||
"label_type_title": "Type of the label will help Trilium to choose suitable interface to enter the label value.",
|
||||
"label_type": "Type",
|
||||
"text": "Text",
|
||||
"textarea": "Multi-line Text",
|
||||
"number": "Number",
|
||||
"boolean": "Boolean",
|
||||
"date": "Date",
|
||||
@@ -376,7 +368,7 @@
|
||||
"calendar_root": "marks note which should be used as root for day notes. Only one should be marked as such.",
|
||||
"archived": "notes with this label won't be visible by default in search results (also in Jump To, Add Link dialogs etc).",
|
||||
"exclude_from_export": "notes (with their sub-tree) won't be included in any note export",
|
||||
"run": "defines on which events script should run. Possible values are:\n<ul>\n<li>frontendStartup - when Trilium frontend starts up (or is refreshed), but not on mobile.</li>\n<li>mobileStartup - when Trilium frontend starts up (or is refreshed), on mobile.</li>\n<li>backendStartup - when Trilium backend starts up.</li>\n<li>hourly - run once an hour. You can use additional label <code>runAtHour</code> to specify at which hour.</li>\n<li>daily - run once a day.</li>\n</ul>",
|
||||
"run": "defines on which events script should run. Possible values are:\n<ul>\n<li>frontendStartup - when Trilium frontend starts up (or is refreshed), but not on mobile.</li>\n<li>mobileStartup - when Trilium frontend starts up (or is refreshed), on mobile.</li>\n<li>backendStartup - when Trilium backend starts up</li>\n<li>hourly - run once an hour. You can use additional label <code>runAtHour</code> to specify at which hour.</li>\n<li>daily - run once a day</li>\n</ul>",
|
||||
"run_on_instance": "Define which trilium instance should run this on. Default to all instances.",
|
||||
"run_at_hour": "On which hour should this run. Should be used together with <code>#run=hourly</code>. Can be defined multiple times for more runs during the day.",
|
||||
"disable_inclusion": "scripts with this label won't be included into parent script execution.",
|
||||
@@ -698,7 +690,6 @@
|
||||
"search_in_note": "Search in note",
|
||||
"note_source": "Note source",
|
||||
"note_attachments": "Note attachments",
|
||||
"view_ocr_text": "View OCR text",
|
||||
"open_note_externally": "Open note externally",
|
||||
"open_note_externally_title": "File will be open in an external application and watched for changes. You'll then be able to upload the modified version back to Trilium.",
|
||||
"open_note_custom": "Open note custom",
|
||||
@@ -813,11 +804,7 @@
|
||||
"board": "Board",
|
||||
"presentation": "Presentation",
|
||||
"include_archived_notes": "Show archived notes",
|
||||
"hide_child_notes": "Hide child notes in tree",
|
||||
"open_all_in_tabs": "Open all",
|
||||
"open_all_in_tabs_tooltip": "Open all results in new tabs",
|
||||
"open_all_confirm": "This will open {{count}} notes in new tabs. Continue?",
|
||||
"open_all_too_many": "Too many results ({{count}}). Maximum is {{max}}."
|
||||
"hide_child_notes": "Hide child notes in tree"
|
||||
},
|
||||
"edited_notes": {
|
||||
"no_edited_notes_found": "No edited notes on this day yet...",
|
||||
@@ -871,8 +858,7 @@
|
||||
"collapse": "Collapse to normal size",
|
||||
"title": "Note Map",
|
||||
"fix-nodes": "Fix nodes",
|
||||
"link-distance": "Link distance",
|
||||
"too-many-notes": "This subtree contains {{count}} notes, which exceeds the limit of {{max}} that can be displayed in the note map."
|
||||
"link-distance": "Link distance"
|
||||
},
|
||||
"note_paths": {
|
||||
"title": "Note Paths",
|
||||
@@ -1082,11 +1068,11 @@
|
||||
"unprotecting-title": "Unprotecting status"
|
||||
},
|
||||
"relation_map": {
|
||||
"open_in_new_tab": "Open in new tab",
|
||||
"remove_note": "Remove note",
|
||||
"edit_title": "Edit title",
|
||||
"rename_note": "Rename note",
|
||||
"enter_new_title": "Enter new note title:",
|
||||
"rename_relation": "Rename relation",
|
||||
"remove_relation": "Remove relation",
|
||||
"confirm_remove_relation": "Are you sure you want to remove the relation?",
|
||||
"specify_new_relation_name": "Specify new relation name (allowed characters: alphanumeric, colon and underscore):",
|
||||
@@ -1171,9 +1157,7 @@
|
||||
"title": "Experimental Options",
|
||||
"disclaimer": "These options are experimental and may cause instability. Use with caution.",
|
||||
"new_layout_name": "New Layout",
|
||||
"new_layout_description": "Try out the new layout for a more modern look and improved usability. Subject to heavy change in the upcoming releases.",
|
||||
"llm_name": "AI / LLM Chat",
|
||||
"llm_description": "Enable the AI chat sidebar and LLM chat notes powered by large language models."
|
||||
"new_layout_description": "Try out the new layout for a more modern look and improved usability. Subject to heavy change in the upcoming releases."
|
||||
},
|
||||
"fonts": {
|
||||
"theme_defined": "Theme defined",
|
||||
@@ -1268,28 +1252,12 @@
|
||||
},
|
||||
"images": {
|
||||
"images_section_title": "Images",
|
||||
"download_images_automatically": "Download images automatically",
|
||||
"download_images_description": "Download referenced online images from pasted HTML so they are available offline.",
|
||||
"enable_image_compression": "Image compression",
|
||||
"enable_image_compression_description": "Compress and resize images when they are uploaded or pasted.",
|
||||
"max_image_dimensions": "Max image dimensions",
|
||||
"max_image_dimensions_description": "Images exceeding this size will be resized automatically.",
|
||||
"download_images_automatically": "Download images automatically for offline use.",
|
||||
"download_images_description": "Pasted HTML can contain references to online images, Trilium will find those references and download the images so that they are available offline.",
|
||||
"enable_image_compression": "Enable image compression",
|
||||
"max_image_dimensions": "Max width / height of an image (image will be resized if it exceeds this setting).",
|
||||
"max_image_dimensions_unit": "pixels",
|
||||
"jpeg_quality": "JPEG quality",
|
||||
"jpeg_quality_description": "Recommended range is 50–85. Lower values reduce file size, higher values preserve detail.",
|
||||
"ocr_section_title": "Text Extraction (OCR)",
|
||||
"ocr_related_content_languages": "Content languages (used for text extraction)",
|
||||
"ocr_auto_process": "Auto-process new files",
|
||||
"ocr_auto_process_description": "Automatically extract text from newly uploaded or pasted files.",
|
||||
"ocr_min_confidence": "Minimum confidence",
|
||||
"ocr_confidence_description": "Only extract text above this confidence threshold. Lower values include more text but may be less accurate.",
|
||||
"batch_ocr_title": "Process Existing Files",
|
||||
"batch_ocr_description": "Extract text from all existing images, PDFs, and Office documents in your notes. This may take some time depending on the number of files.",
|
||||
"batch_ocr_start": "Start Batch Processing",
|
||||
"batch_ocr_starting": "Starting batch processing...",
|
||||
"batch_ocr_progress": "Processing {{processed}} of {{total}} files...",
|
||||
"batch_ocr_completed": "Batch processing completed! Processed {{processed}} files.",
|
||||
"batch_ocr_error": "Error during batch processing: {{error}}"
|
||||
"jpeg_quality_description": "JPEG quality (10 - worst quality, 100 - best quality, 50 - 85 is recommended)"
|
||||
},
|
||||
"attachment_erasure_timeout": {
|
||||
"attachment_erasure_timeout": "Attachment Erasure Timeout",
|
||||
@@ -1324,6 +1292,10 @@
|
||||
"erase_excess_revision_snapshots": "Erase excess revision snapshots now",
|
||||
"erase_excess_revision_snapshots_prompt": "Excess revision snapshots have been erased."
|
||||
},
|
||||
"search": {
|
||||
"title": "Search",
|
||||
"enable_fuzzy_matching": "Enable fuzzy matching in search (matches similar words when exact matches are insufficient)"
|
||||
},
|
||||
"search_engine": {
|
||||
"title": "Search Engine",
|
||||
"custom_search_engine_info": "Custom search engine requires both a name and a URL to be set. If either of these is not set, DuckDuckGo will be used as the default search engine.",
|
||||
@@ -1335,7 +1307,7 @@
|
||||
"custom_name_label": "Custom search engine name",
|
||||
"custom_name_placeholder": "Customize search engine name",
|
||||
"custom_url_label": "Custom search engine URL should include {keyword} as a placeholder for the search term.",
|
||||
"custom_url_placeholder": "Customize search engine URL",
|
||||
"custom_url_placeholder": "Customize search engine url",
|
||||
"save_button": "Save"
|
||||
},
|
||||
"tray": {
|
||||
@@ -1413,8 +1385,7 @@
|
||||
"date-and-time": "Date & time",
|
||||
"path": "Path",
|
||||
"database_backed_up_to": "Database has been backed up to {{backupFilePath}}",
|
||||
"no_backup_yet": "no backup yet",
|
||||
"download": "Download"
|
||||
"no_backup_yet": "no backup yet"
|
||||
},
|
||||
"etapi": {
|
||||
"title": "ETAPI",
|
||||
@@ -1512,21 +1483,18 @@
|
||||
"spellcheck": {
|
||||
"title": "Spell Check",
|
||||
"description": "These options apply only for desktop builds, browsers will use their own native spell check.",
|
||||
"enable": "Check spelling",
|
||||
"language_code_label": "Spell Check Languages",
|
||||
"restart-required": "Changes to the spell check options will take effect after application restart.",
|
||||
"custom_dictionary_title": "Custom Dictionary",
|
||||
"custom_dictionary_description": "Words added to the dictionary are synced across all your devices.",
|
||||
"custom_dictionary_edit": "Custom words",
|
||||
"custom_dictionary_edit_description": "Edit the list of words that should not be flagged by the spell checker. Changes will be visible after a restart.",
|
||||
"custom_dictionary_open": "Edit dictionary",
|
||||
"related_description": "Configure spell check languages and custom dictionary."
|
||||
"enable": "Enable spellcheck",
|
||||
"language_code_label": "Language code(s)",
|
||||
"language_code_placeholder": "for example \"en-US\", \"de-AT\"",
|
||||
"multiple_languages_info": "Multiple languages can be separated by comma, e.g. \"en-US, de-DE, cs\". ",
|
||||
"available_language_codes_label": "Available language codes:",
|
||||
"restart-required": "Changes to the spell check options will take effect after application restart."
|
||||
},
|
||||
"sync_2": {
|
||||
"config_title": "Sync Configuration",
|
||||
"server_address": "Server instance address",
|
||||
"timeout": "Sync timeout",
|
||||
"timeout_description": "How long to wait before giving up on a slow sync connection. Increase if you have an unstable network.",
|
||||
"timeout_unit": "milliseconds",
|
||||
"proxy_label": "Sync proxy server (optional)",
|
||||
"note": "Note",
|
||||
"note_description": "If you leave the proxy setting blank, the system proxy will be used (applies to desktop/electron build only).",
|
||||
@@ -1635,7 +1603,6 @@
|
||||
"geo-map": "Geo Map",
|
||||
"beta-feature": "Beta",
|
||||
"ai-chat": "AI Chat",
|
||||
"llm-chat": "AI Chat",
|
||||
"task-list": "Task List",
|
||||
"new-feature": "New",
|
||||
"collections": "Collections",
|
||||
@@ -1647,49 +1614,6 @@
|
||||
"toggle-on-hint": "Note is not protected, click to make it protected",
|
||||
"toggle-off-hint": "Note is protected, click to make it unprotected"
|
||||
},
|
||||
"llm_chat": {
|
||||
"placeholder": "Type a message...",
|
||||
"send": "Send",
|
||||
"sending": "Sending...",
|
||||
"empty_state": "Start a conversation by typing a message below.",
|
||||
"searching_web": "Searching the web...",
|
||||
"web_search": "Web search",
|
||||
"note_tools": "Note access",
|
||||
"sources": "Sources",
|
||||
"sources_summary": "{{count}} sources from {{sites}} sites",
|
||||
"extended_thinking": "Extended thinking",
|
||||
"legacy_models": "Legacy models",
|
||||
"thinking": "Thinking...",
|
||||
"thought_process": "Thought process",
|
||||
"tool_calls": "{{count}} tool call(s)",
|
||||
"input": "Input",
|
||||
"result": "Result",
|
||||
"error": "Error",
|
||||
"tool_error": "failed",
|
||||
"total_tokens": "{{total}} tokens",
|
||||
"tokens_detail": "{{prompt}} prompt + {{completion}} completion",
|
||||
"tokens_used": "{{prompt}} prompt + {{completion}} completion = {{total}} tokens",
|
||||
"tokens_used_with_cost": "{{prompt}} prompt + {{completion}} completion = {{total}} tokens (~${{cost}})",
|
||||
"tokens_used_with_model": "{{model}}: {{prompt}} prompt + {{completion}} completion = {{total}} tokens",
|
||||
"tokens_used_with_model_and_cost": "{{model}}: {{prompt}} prompt + {{completion}} completion = {{total}} tokens (~${{cost}})",
|
||||
"tokens": "tokens",
|
||||
"context_used": "{{percentage}}% used",
|
||||
"note_context_enabled": "Click to disable note context: {{title}}",
|
||||
"note_context_disabled": "Click to include current note in context",
|
||||
"no_provider_message": "No AI provider configured. Add one to start chatting.",
|
||||
"add_provider": "Add AI Provider",
|
||||
"stop": "Stop"
|
||||
},
|
||||
"sidebar_chat": {
|
||||
"title": "AI Chat",
|
||||
"launcher_title": "Open AI Chat",
|
||||
"new_chat": "Start new chat",
|
||||
"save_chat": "Save chat to notes",
|
||||
"empty_state": "Start a conversation",
|
||||
"history": "Chat history",
|
||||
"recent_chats": "Recent chats",
|
||||
"no_chats": "No previous chats"
|
||||
},
|
||||
"shared_switch": {
|
||||
"shared": "Shared",
|
||||
"toggle-on-title": "Share the note",
|
||||
@@ -1884,8 +1808,7 @@
|
||||
"theme_none": "No syntax highlighting",
|
||||
"theme_group_light": "Light themes",
|
||||
"theme_group_dark": "Dark themes",
|
||||
"copy_title": "Copy to clipboard",
|
||||
"click_to_copy": "Click to copy"
|
||||
"copy_title": "Copy to clipboard"
|
||||
},
|
||||
"classic_editor_toolbar": {
|
||||
"title": "Formatting"
|
||||
@@ -2002,7 +1925,7 @@
|
||||
},
|
||||
"content_language": {
|
||||
"title": "Content languages",
|
||||
"description": "Select one or more languages that should appear in the language selection in the Basic Properties section of a read-only or editable text note. This will allow features such as spell-checking, right-to-left support and text extraction (OCR)."
|
||||
"description": "Select one or more languages that should appear in the language selection in the Basic Properties section of a read-only or editable text note. This will allow features such as spell-checking or right-to-left support."
|
||||
},
|
||||
"switch_layout_button": {
|
||||
"title_vertical": "Move editing pane to the bottom",
|
||||
@@ -2102,22 +2025,6 @@
|
||||
"calendar_view": {
|
||||
"delete_note": "Delete note..."
|
||||
},
|
||||
"ocr": {
|
||||
"extracted_text": "Extracted Text (OCR)",
|
||||
"extracted_text_title": "Extracted Text (OCR)",
|
||||
"loading_text": "Loading OCR text...",
|
||||
"no_text_available": "No OCR text available",
|
||||
"no_text_explanation": "This note has not been processed for OCR text extraction or no text was found.",
|
||||
"failed_to_load": "Failed to load OCR text",
|
||||
"process_now": "Process OCR",
|
||||
"processing": "Processing...",
|
||||
"processing_started": "OCR processing has been started. Please wait a moment and refresh.",
|
||||
"processing_complete": "OCR processing complete.",
|
||||
"processing_failed": "Failed to start OCR processing",
|
||||
"text_filtered_low_confidence": "OCR detected text with {{confidence}}% confidence, but it was discarded because your minimum threshold is {{threshold}}%.",
|
||||
"open_media_settings": "Open Settings",
|
||||
"view_extracted_text": "View extracted text (OCR)"
|
||||
},
|
||||
"command_palette": {
|
||||
"tree-action-name": "Tree: {{name}}",
|
||||
"export_note_title": "Export Note",
|
||||
@@ -2299,94 +2206,5 @@
|
||||
},
|
||||
"setup_form": {
|
||||
"more_info": "Learn more"
|
||||
},
|
||||
"mermaid": {
|
||||
"placeholder": "Type the content of your Mermaid diagram or use one of the sample diagrams below.",
|
||||
"sample_diagrams": "Sample diagrams:",
|
||||
"sample_flowchart": "Flowchart",
|
||||
"sample_class": "Class",
|
||||
"sample_sequence": "Sequence",
|
||||
"sample_entity_relationship": "Entity Relationship",
|
||||
"sample_state": "State",
|
||||
"sample_mindmap": "Mindmap",
|
||||
"sample_architecture": "Architecture",
|
||||
"sample_block": "Block",
|
||||
"sample_c4": "C4",
|
||||
"sample_gantt": "Gantt",
|
||||
"sample_git": "Git",
|
||||
"sample_kanban": "Kanban",
|
||||
"sample_packet": "Packet",
|
||||
"sample_pie": "Pie",
|
||||
"sample_quadrant": "Quadrant",
|
||||
"sample_radar": "Radar",
|
||||
"sample_requirement": "Requirement",
|
||||
"sample_sankey": "Sankey",
|
||||
"sample_timeline": "Timeline",
|
||||
"sample_treemap": "Treemap",
|
||||
"sample_user_journey": "User Journey",
|
||||
"sample_xy": "XY",
|
||||
"sample_venn": "Venn",
|
||||
"sample_ishikawa": "Ishikawa",
|
||||
"sample_treeview": "TreeView",
|
||||
"sample_wardley": "Wardley Map"
|
||||
},
|
||||
"mind-map": {
|
||||
"addChild": "Add child",
|
||||
"addParent": "Add parent",
|
||||
"addSibling": "Add sibling",
|
||||
"removeNode": "Remove node",
|
||||
"focus": "Focus Mode",
|
||||
"cancelFocus": "Cancel Focus Mode",
|
||||
"moveUp": "Move up",
|
||||
"moveDown": "Move down",
|
||||
"link": "Link",
|
||||
"linkBidirectional": "Bidirectional Link",
|
||||
"clickTips": "Please click the target node",
|
||||
"summary": "Summary"
|
||||
},
|
||||
"llm": {
|
||||
"settings_title": "AI / LLM",
|
||||
"settings_description": "Configure AI and Large Language Model integrations.",
|
||||
"feature_not_enabled": "Enable the LLM experimental feature in Settings → Advanced → Experimental features to use AI integrations.",
|
||||
"add_provider": "Add Provider",
|
||||
"add_provider_title": "Add AI Provider",
|
||||
"configured_providers": "Configured Providers",
|
||||
"no_providers_configured": "No providers configured yet.",
|
||||
"provider_name": "Name",
|
||||
"provider_type": "Provider",
|
||||
"actions": "Actions",
|
||||
"delete_provider": "Delete",
|
||||
"delete_provider_confirmation": "Are you sure you want to delete the provider \"{{name}}\"?",
|
||||
"api_key": "API Key",
|
||||
"api_key_placeholder": "Enter your API key",
|
||||
"cancel": "Cancel",
|
||||
"mcp_title": "MCP (Model Context Protocol)",
|
||||
"mcp_enabled": "MCP server",
|
||||
"mcp_enabled_description": "Expose a Model Context Protocol (MCP) endpoint so that AI coding assistants (e.g. Claude Code, GitHub Copilot) can read and modify your notes. The endpoint is only accessible from localhost.",
|
||||
"mcp_endpoint_title": "Endpoint URL",
|
||||
"mcp_endpoint_description": "Add this URL to your AI assistant's MCP configuration",
|
||||
"tools": {
|
||||
"search_notes": "Search notes",
|
||||
"get_note": "Get note",
|
||||
"get_note_content": "Get note content",
|
||||
"update_note_content": "Update note content",
|
||||
"append_to_note": "Append to note",
|
||||
"create_note": "Create note",
|
||||
"get_attributes": "Get attributes",
|
||||
"get_attribute": "Get attribute",
|
||||
"set_attribute": "Set attribute",
|
||||
"delete_attribute": "Delete attribute",
|
||||
"get_child_notes": "Get child notes",
|
||||
"get_subtree": "Get subtree",
|
||||
"load_skill": "Load skill",
|
||||
"web_search": "Web search",
|
||||
"note_in_parent": "<Note/> in <Parent/>",
|
||||
"get_attachment": "Get attachment",
|
||||
"get_attachment_content": "Read attachment content",
|
||||
"rename_note": "Rename note",
|
||||
"delete_note": "Delete note",
|
||||
"move_note": "Move note",
|
||||
"clone_note": "Clone note"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
"also_delete_note": "También eliminar la nota"
|
||||
},
|
||||
"delete_notes": {
|
||||
"delete_notes_preview": "Eliminar vista previa de notas",
|
||||
"close": "Cerrar",
|
||||
"delete_all_clones_description": "Eliminar también todos los clones (se puede deshacer en cambios recientes)",
|
||||
"erase_notes_description": "La eliminación normal (suave) solo marca las notas como eliminadas y se pueden recuperar (en el cuadro de diálogo de cambios recientes) dentro de un periodo de tiempo. Al marcar esta opción se borrarán las notas inmediatamente y no será posible recuperarlas.",
|
||||
@@ -95,7 +96,9 @@
|
||||
"notes_to_be_deleted": "Las siguientes notas serán eliminadas ({{notesCount}})",
|
||||
"no_note_to_delete": "No se eliminará ninguna nota (solo clones).",
|
||||
"broken_relations_to_be_deleted": "Las siguientes relaciones se romperán y serán eliminadas ({{ relationCount}})",
|
||||
"cancel": "Cancelar"
|
||||
"cancel": "Cancelar",
|
||||
"ok": "Aceptar",
|
||||
"deleted_relation_text": "Nota {{- note}} (para ser eliminada) está referenciado por la relación {{- relation}} que se origina en {{- source}}."
|
||||
},
|
||||
"export": {
|
||||
"export_note_title": "Exportar nota",
|
||||
@@ -1048,6 +1051,7 @@
|
||||
"unprotecting-title": "Estado de desprotección"
|
||||
},
|
||||
"relation_map": {
|
||||
"open_in_new_tab": "Abrir en nueva pestaña",
|
||||
"remove_note": "Quitar nota",
|
||||
"edit_title": "Editar título",
|
||||
"rename_note": "Cambiar nombre de nota",
|
||||
@@ -1329,8 +1333,7 @@
|
||||
"date-and-time": "Fecha y hora",
|
||||
"path": "Ruta",
|
||||
"database_backed_up_to": "Se ha realizado una copia de seguridad de la base de datos en {{backupFilePath}}",
|
||||
"no_backup_yet": "no hay copia de seguridad todavía",
|
||||
"download": "Descargar"
|
||||
"no_backup_yet": "no hay copia de seguridad todavía"
|
||||
},
|
||||
"etapi": {
|
||||
"title": "ETAPI",
|
||||
@@ -1430,12 +1433,16 @@
|
||||
"description": "Estas opciones se aplican sólo para compilaciones de escritorio; los navegadores utilizarán su corrector ortográfico nativo.",
|
||||
"enable": "Habilitar corrector ortográfico",
|
||||
"language_code_label": "Código(s) de idioma",
|
||||
"language_code_placeholder": "por ejemplo \"en-US\", \"de-AT\"",
|
||||
"multiple_languages_info": "Múltiples idiomas se pueden separar por coma, por ejemplo \"en-US, de-DE, cs\". ",
|
||||
"available_language_codes_label": "Códigos de idioma disponibles:",
|
||||
"restart-required": "Los cambios en las opciones de corrección ortográfica entrarán en vigor después del reinicio de la aplicación."
|
||||
},
|
||||
"sync_2": {
|
||||
"config_title": "Configuración de sincronización",
|
||||
"server_address": "Dirección de la instancia del servidor",
|
||||
"timeout": "Tiempo de espera de sincronización (milisegundos)",
|
||||
"timeout_unit": "milisegundos",
|
||||
"proxy_label": "Sincronizar servidor proxy (opcional)",
|
||||
"note": "Nota",
|
||||
"note_description": "Si deja la configuración del proxy en blanco, se utilizará el proxy del sistema (se aplica únicamente a la compilación de escritorio/electron).",
|
||||
@@ -2191,52 +2198,5 @@
|
||||
},
|
||||
"setup_form": {
|
||||
"more_info": "Para saber más"
|
||||
},
|
||||
"media": {
|
||||
"play": "Reproducir (Espacio)",
|
||||
"pause": "Pausa (Espacio)",
|
||||
"back-10s": "Retroceder 10s (tecla de flecha izquierda)",
|
||||
"forward-30s": "Adelantar 30s",
|
||||
"mute": "Silenciar (M)",
|
||||
"unmute": "Activar sonido (M)",
|
||||
"playback-speed": "Velocidad de reproducción",
|
||||
"loop": "Bucle",
|
||||
"disable-loop": "Deshabilitar bucle",
|
||||
"rotate": "Rotar",
|
||||
"picture-in-picture": "Imagen en imagen",
|
||||
"exit-picture-in-picture": "Salir del modo imagen en imagen",
|
||||
"fullscreen": "Pantalla completa (F)",
|
||||
"exit-fullscreen": "Salir de la pantalla completa",
|
||||
"unsupported-format": "La vista previa del medio no está disponible para este formato de archivo:\n{{mime}}",
|
||||
"zoom-to-fit": "Acercamiento para llenar",
|
||||
"zoom-reset": "Reiniciar acercamiento para llenar"
|
||||
},
|
||||
"mermaid": {
|
||||
"placeholder": "Ingrese el contenido de su diagrama Mermaid o utilice uno de los diagramas de muestra a continuación.",
|
||||
"sample_diagrams": "Diagramas de muestra:",
|
||||
"sample_flowchart": "Diagrama de flujo",
|
||||
"sample_class": "Clase",
|
||||
"sample_sequence": "Secuencia",
|
||||
"sample_entity_relationship": "Relación entre entidades",
|
||||
"sample_state": "Estado",
|
||||
"sample_mindmap": "Mapa mental",
|
||||
"sample_architecture": "Arquitectura",
|
||||
"sample_block": "Bloque",
|
||||
"sample_c4": "C4",
|
||||
"sample_gantt": "Gantt",
|
||||
"sample_git": "Git",
|
||||
"sample_kanban": "Kanban",
|
||||
"sample_packet": "Paquete",
|
||||
"sample_pie": "Pastel",
|
||||
"sample_quadrant": "Cuadrante",
|
||||
"sample_radar": "Radar",
|
||||
"sample_requirement": "Requerimiento",
|
||||
"sample_sankey": "Sankey",
|
||||
"sample_timeline": "Línea de tiempo",
|
||||
"sample_user_journey": "Jornada de usuario",
|
||||
"sample_xy": "XY",
|
||||
"sample_venn": "Venn",
|
||||
"sample_ishikawa": "Ishikawa",
|
||||
"sample_treemap": "Mapa de árbol"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,10 +62,12 @@
|
||||
"also_delete_note": "Poista myös muistio"
|
||||
},
|
||||
"delete_notes": {
|
||||
"delete_notes_preview": "Poista muistion esikatselu",
|
||||
"close": "Sulje",
|
||||
"notes_to_be_deleted": "Seuraavat muistiot tullaan poistamaan ({{notesCount}})",
|
||||
"no_note_to_delete": "Muistioita ei poisteta (vain kopiot).",
|
||||
"cancel": "Peruuta"
|
||||
"cancel": "Peruuta",
|
||||
"ok": "OK"
|
||||
},
|
||||
"export": {
|
||||
"export_note_title": "Vie muistio",
|
||||
|
||||
@@ -28,10 +28,7 @@
|
||||
},
|
||||
"widget-render-error": {
|
||||
"title": "Rendu impossible d'un widget React custom"
|
||||
},
|
||||
"widget-missing-parent": "Le widget personnalisé ne comprend pas de propriété '{{property}}' définie\n\nSi ce script est prévu pour être exécuté sans fonctionnalité UI, utilisez '#run=frontendStartup' plutôt.",
|
||||
"open-script-note": "Ouvrir une note script",
|
||||
"scripting-error": "Échec du script personnalisé : {{title}}"
|
||||
}
|
||||
},
|
||||
"add_link": {
|
||||
"add_link": "Ajouter un lien",
|
||||
@@ -49,7 +46,7 @@
|
||||
"prefix": "Préfixe : ",
|
||||
"save": "Sauvegarder",
|
||||
"branch_prefix_saved": "Le préfixe de la branche a été enregistré.",
|
||||
"edit_branch_prefix_multiple": "Modifier le préfixe pour {{count}} branches",
|
||||
"edit_branch_prefix_multiple": "Modifier le préfixe de branche pour {{count}} branches",
|
||||
"branch_prefix_saved_multiple": "Le préfixe de la branche a été sauvegardé pour {{count}} branches.",
|
||||
"affected_branches": "Branches impactées ({{count}}):"
|
||||
},
|
||||
@@ -88,6 +85,7 @@
|
||||
"also_delete_note": "Supprimer également la note"
|
||||
},
|
||||
"delete_notes": {
|
||||
"delete_notes_preview": "Supprimer la note",
|
||||
"close": "Fermer",
|
||||
"delete_all_clones_description": "Supprimer aussi les clones (peut être annulé dans des modifications récentes)",
|
||||
"erase_notes_description": "La suppression normale (douce) marque uniquement les notes comme supprimées et elles peuvent être restaurées (dans la boîte de dialogue des Modifications récentes) dans un délai donné. Cocher cette option effacera les notes immédiatement et il ne sera pas possible de les restaurer.",
|
||||
@@ -95,7 +93,9 @@
|
||||
"notes_to_be_deleted": "Les notes suivantes seront supprimées ({{notesCount}})",
|
||||
"no_note_to_delete": "Aucune note ne sera supprimée (uniquement les clones).",
|
||||
"broken_relations_to_be_deleted": "Les relations suivantes seront rompues et supprimées ({{ relationCount}})",
|
||||
"cancel": "Annuler"
|
||||
"cancel": "Annuler",
|
||||
"ok": "OK",
|
||||
"deleted_relation_text": "Note {{- note}} (à supprimer) est référencée dans la relation {{- relation}} provenant de {{- source}}."
|
||||
},
|
||||
"export": {
|
||||
"export_note_title": "Exporter la note",
|
||||
@@ -114,7 +114,7 @@
|
||||
"export_in_progress": "Exportation en cours : {{progressCount}}",
|
||||
"export_finished_successfully": "L'exportation s'est terminée avec succès.",
|
||||
"format_pdf": "PDF - pour l'impression ou le partage de documents.",
|
||||
"share-format": "HTML pour la publication Web : utilise le même thème que celui utilisé pour les notes partagées, mais peut être publié sous forme de site Web statique."
|
||||
"share-format": "HTML pour la publication Web - utilise le même thème que celui utilisé pour les notes partagées, mais peut être publié sous forme de site Web statique."
|
||||
},
|
||||
"help": {
|
||||
"noteNavigation": "Navigation dans les notes",
|
||||
@@ -443,8 +443,7 @@
|
||||
"and_more": "... et {{count}} plus.",
|
||||
"print_landscape": "Lors de l'exportation en PDF, change l'orientation de la page en paysage au lieu de portrait.",
|
||||
"print_page_size": "Lors de l'exportation en PDF, change la taille de la page. Valeurs supportées : <code>A0</code>, <code>A1</code>, <code>A2</code>, <code>A3</code>, <code>A4</code>, <code>A5</code>, <code>A6</code>, <code>Legal</code>, <code>Letter</code>, <code>Tabloid</code>, <code>Ledger</code>.",
|
||||
"color_type": "Couleur",
|
||||
"textarea": "Texte multiligne"
|
||||
"color_type": "Couleur"
|
||||
},
|
||||
"attribute_editor": {
|
||||
"help_text_body1": "Pour ajouter un label, tapez simplement par ex. <code>#rock</code>, ou si vous souhaitez également ajouter une valeur, tapez par ex. <code>#année = 2020</code>",
|
||||
@@ -660,8 +659,7 @@
|
||||
"show-cheatsheet": "Afficher l'aide rapide",
|
||||
"toggle-zen-mode": "Zen Mode",
|
||||
"new-version-available": "Nouvelle mise à jour disponible",
|
||||
"download-update": "Obtenir la version {{latestVersion}}",
|
||||
"search_notes": "Rechercher notes"
|
||||
"download-update": "Obtenir la version {{latestVersion}}"
|
||||
},
|
||||
"zen_mode": {
|
||||
"button_exit": "Sortir du Zen mode"
|
||||
@@ -705,8 +703,7 @@
|
||||
"advanced": "Avancé",
|
||||
"export_as_image": "Exporter en tant qu'image",
|
||||
"export_as_image_png": "PNG",
|
||||
"export_as_image_svg": "SVG (vectoriel)",
|
||||
"note_map": "Note Carte"
|
||||
"export_as_image_svg": "SVG (vectoriel)"
|
||||
},
|
||||
"onclick_button": {
|
||||
"no_click_handler": "Le widget bouton '{{componentId}}' n'a pas de gestionnaire de clic défini"
|
||||
@@ -744,25 +741,23 @@
|
||||
"button_title": "Exporter le diagramme au format SVG"
|
||||
},
|
||||
"relation_map_buttons": {
|
||||
"create_child_note_title": "Créer une note enfant et l'ajouter à la carte",
|
||||
"create_child_note_title": "Créer une nouvelle note enfant et l'ajouter à cette carte de relation",
|
||||
"reset_pan_zoom_title": "Réinitialiser le panoramique et le zoom aux coordonnées et à la position initiales",
|
||||
"zoom_in_title": "Zoomer",
|
||||
"zoom_out_title": "Zoom arrière"
|
||||
},
|
||||
"zpetne_odkazy": {
|
||||
"relation": "relation",
|
||||
"backlink_one": "{{count}} Rétrolien",
|
||||
"backlink_many": "{{count}} Rétroliens",
|
||||
"backlink_other": "{{count}} Rétrolien"
|
||||
"backlink_one": "{{count}} Lien inverse",
|
||||
"backlink_many": "",
|
||||
"backlink_other": "{{count}} Liens inverses"
|
||||
},
|
||||
"mobile_detail_menu": {
|
||||
"insert_child_note": "Insérer une note enfant",
|
||||
"delete_this_note": "Supprimer cette note",
|
||||
"error_cannot_get_branch_id": "Impossible d'obtenir branchId pour notePath '{{notePath}}'",
|
||||
"error_unrecognized_command": "Commande non reconnue {{command}}",
|
||||
"note_revisions": "Révision de la note",
|
||||
"backlinks": "Rétro-liens",
|
||||
"content_language_switcher": "Langue du contenu: {{language}}"
|
||||
"note_revisions": "Révision de la note"
|
||||
},
|
||||
"note_icon": {
|
||||
"change_note_icon": "Changer l'icône de note",
|
||||
@@ -771,12 +766,7 @@
|
||||
"filter": "Filtre",
|
||||
"filter-none": "Toutes les icônes",
|
||||
"filter-default": "Icônes par défaut",
|
||||
"icon_tooltip": "{{name}}\nPack d'icônes : {{iconPack}}",
|
||||
"no_results": "Aucune icône trouvée.",
|
||||
"search_placeholder_one": "{{number}} icône recherchées parmi {{count}} packs.",
|
||||
"search_placeholder_many": "{{number}} icônes recherchées parmi {{count}} packs.",
|
||||
"search_placeholder_other": "{{number}} icônes recherchées parmi {{count}} packs.",
|
||||
"search_placeholder_filtered": "Rechercher {{number}} icônes dans {{name}}"
|
||||
"icon_tooltip": "{{name}}\nPack d'icônes : {{iconPack}}"
|
||||
},
|
||||
"basic_properties": {
|
||||
"note_type": "Type de note",
|
||||
@@ -792,7 +782,7 @@
|
||||
"collapse_all_notes": "Réduire toutes les notes",
|
||||
"collapse": "Réduire",
|
||||
"expand": "Développer",
|
||||
"invalid_view_type": "Type de vue '{{type}}' non valide",
|
||||
"invalid_view_type": "Type de vue non valide '{{type}}'",
|
||||
"calendar": "Calendrier",
|
||||
"book_properties": "Propriétés de la collection",
|
||||
"table": "Tableau",
|
||||
@@ -803,8 +793,7 @@
|
||||
"expand_tooltip": "Développe les éléments enfants directs de cette collection (à un niveau). Pour plus d'options, appuyez sur la flèche à droite.",
|
||||
"expand_first_level": "Développer les enfants directs",
|
||||
"expand_nth_level": "Développer sur {{depth}} niveaux",
|
||||
"expand_all_levels": "Développer tous les niveaux",
|
||||
"hide_child_notes": "Masquer les notes enfants dans l’arborescence"
|
||||
"expand_all_levels": "Développer tous les niveaux"
|
||||
},
|
||||
"edited_notes": {
|
||||
"no_edited_notes_found": "Aucune note modifiée ce jour-là...",
|
||||
@@ -817,7 +806,7 @@
|
||||
"file_type": "Type de fichier",
|
||||
"file_size": "Taille du fichier",
|
||||
"download": "Télécharger",
|
||||
"open": "Ouvrir dans une nouvelle fenêtre",
|
||||
"open": "Ouvrir",
|
||||
"upload_new_revision": "Téléverser une nouvelle version",
|
||||
"upload_success": "Une nouvelle version de fichier a été téléversée.",
|
||||
"upload_failed": "Le téléversement d'une nouvelle version de fichier a échoué.",
|
||||
@@ -837,8 +826,7 @@
|
||||
},
|
||||
"inherited_attribute_list": {
|
||||
"title": "Attributs hérités",
|
||||
"no_inherited_attributes": "Aucun attribut hérité.",
|
||||
"none": "aucun"
|
||||
"no_inherited_attributes": "Aucun attribut hérité."
|
||||
},
|
||||
"note_info_widget": {
|
||||
"note_id": "Identifiant de la note",
|
||||
@@ -915,8 +903,7 @@
|
||||
"unknown_search_option": "Option de recherche inconnue {{searchOptionName}}",
|
||||
"search_note_saved": "La note de recherche a été enregistrée dans {{- notePathTitle}}",
|
||||
"actions_executed": "Les actions ont été exécutées.",
|
||||
"view_options": "Afficher les options:",
|
||||
"option": "option"
|
||||
"view_options": "Afficher les options:"
|
||||
},
|
||||
"similar_notes": {
|
||||
"title": "Notes similaires",
|
||||
@@ -1010,7 +997,7 @@
|
||||
"no_attachments": "Cette note ne contient aucune pièce jointe."
|
||||
},
|
||||
"book": {
|
||||
"no_children_help": "Cette collection ne contient pas de notes enfants, il n'y a donc rien à afficher.",
|
||||
"no_children_help": "Cette note de type Livre n'a aucune note enfant, donc il n'y a rien à afficher. Consultez le <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">wiki</a> pour plus de détails.",
|
||||
"drag_locked_title": "Edition verrouillée",
|
||||
"drag_locked_message": "Le glisser-déposer n'est pas autorisé car l'édition de cette collection est verrouillé."
|
||||
},
|
||||
@@ -1049,6 +1036,7 @@
|
||||
"unprotecting-title": "Statut de la non-protection"
|
||||
},
|
||||
"relation_map": {
|
||||
"open_in_new_tab": "Ouvrir dans un nouvel onglet",
|
||||
"remove_note": "Supprimer la note",
|
||||
"edit_title": "Modifier le titre",
|
||||
"rename_note": "Renommer la note",
|
||||
@@ -1184,8 +1172,8 @@
|
||||
},
|
||||
"code_mime_types": {
|
||||
"title": "Types MIME disponibles dans la liste déroulante",
|
||||
"tooltip_syntax_highlighting": "Mise en évidence de la syntaxe",
|
||||
"tooltip_code_block_syntax": "Blocs de code dans les notes textuelles",
|
||||
"tooltip_syntax_highlighting": "Souligner la syntaxe",
|
||||
"tooltip_code_block_syntax": "Blocs de code dans les notes de texte",
|
||||
"tooltip_code_note_syntax": "Notes de code"
|
||||
},
|
||||
"vim_key_bindings": {
|
||||
@@ -1380,14 +1368,16 @@
|
||||
"description": "Description",
|
||||
"reload_app": "Recharger l'application pour appliquer les modifications",
|
||||
"set_all_to_default": "Réinitialiser aux valeurs par défaut",
|
||||
"confirm_reset": "Voulez-vous vraiment réinitialiser tous les raccourcis clavier par défaut ?",
|
||||
"no_results": "Aucun raccourci correspondant à '{{filter}}'"
|
||||
"confirm_reset": "Voulez-vous vraiment réinitialiser tous les raccourcis clavier par défaut ?"
|
||||
},
|
||||
"spellcheck": {
|
||||
"title": "Vérification orthographique",
|
||||
"description": "Ces options s'appliquent uniquement aux versions de bureau, les navigateurs utiliseront leur propre vérification orthographique native.",
|
||||
"enable": "Activer la vérification orthographique",
|
||||
"language_code_label": "Code(s) de langue",
|
||||
"language_code_placeholder": "par exemple \"fr-FR\", \"en-US\", \"de-AT\"",
|
||||
"multiple_languages_info": "Plusieurs langues peuvent être séparées par une virgule, par ex. \"fr-FR, en-US, de-DE, cs\". ",
|
||||
"available_language_codes_label": "Codes de langue disponibles :",
|
||||
"restart-required": "Les modifications apportées aux options de vérification orthographique prendront effet après le redémarrage de l'application."
|
||||
},
|
||||
"sync_2": {
|
||||
@@ -1403,7 +1393,8 @@
|
||||
"test_title": "Test de synchronisation",
|
||||
"test_description": "Testera la connexion et la prise de contact avec le serveur de synchronisation. Si le serveur de synchronisation n'est pas initialisé, cela le configurera pour qu'il se synchronise avec le document local.",
|
||||
"test_button": "Tester la synchronisation",
|
||||
"handshake_failed": "Échec de la négociation avec le serveur de synchronisation, erreur : {{message}}"
|
||||
"handshake_failed": "Échec de la négociation avec le serveur de synchronisation, erreur : {{message}}",
|
||||
"timeout_unit": "millisecondes"
|
||||
},
|
||||
"api_log": {
|
||||
"close": "Fermer"
|
||||
@@ -1412,7 +1403,7 @@
|
||||
"will_be_deleted_in": "Cette pièce jointe sera automatiquement supprimée dans {{time}}",
|
||||
"will_be_deleted_soon": "Cette pièce jointe sera bientôt supprimée automatiquement",
|
||||
"deletion_reason": ", car la pièce jointe n'est pas liée dans le contenu de la note. Pour empêcher la suppression, ajoutez à nouveau le lien de la pièce jointe dans le contenu d'une note ou convertissez la pièce jointe en note.",
|
||||
"role_and_size": "Rôle : {{role}}, Taille : {{size}}, MIME: {{- mimeType}}",
|
||||
"role_and_size": "Rôle : {{role}}, Taille : {{size}}",
|
||||
"link_copied": "Lien de pièce jointe copié dans le presse-papiers.",
|
||||
"unrecognized_role": "Rôle de pièce jointe « {{role}} » non reconnu."
|
||||
},
|
||||
@@ -1463,13 +1454,10 @@
|
||||
"import-into-note": "Importer dans la note",
|
||||
"apply-bulk-actions": "Appliquer des Actions groupées",
|
||||
"converted-to-attachments": "Les notes {{count}} ont été converties en pièces jointes.",
|
||||
"convert-to-attachment-confirm": "Êtes-vous sûr de vouloir convertir les notes sélectionnées en pièces jointes de leurs notes parentales ? Cette opération s'applique uniquement aux notes d'image, les autres notes seront ignorées.",
|
||||
"convert-to-attachment-confirm": "Êtes-vous sûr de vouloir convertir les notes sélectionnées en pièces jointes de leurs notes parentes ?",
|
||||
"archive": "Archive",
|
||||
"unarchive": "Désarchiver",
|
||||
"open-in-popup": "Modification rapide",
|
||||
"open-in-a-new-window": "Ouvrir dans une nouvelle fenêtre",
|
||||
"hide-subtree": "Masquer le sous-arbre",
|
||||
"show-subtree": "Afficher le sous-arbre"
|
||||
"open-in-popup": "Modification rapide"
|
||||
},
|
||||
"shared_info": {
|
||||
"shared_publicly": "Cette note est partagée publiquement sur {{- link}}.",
|
||||
@@ -1498,10 +1486,7 @@
|
||||
"task-list": "Liste de tâches",
|
||||
"book": "Collection",
|
||||
"new-feature": "Nouveau",
|
||||
"collections": "Collections",
|
||||
"ai-chat": "Chat IA",
|
||||
"llm-chat": "Chat AI",
|
||||
"spreadsheet": "Feuille de calcul"
|
||||
"collections": "Collections"
|
||||
},
|
||||
"protect_note": {
|
||||
"toggle-on": "Protéger la note",
|
||||
@@ -1532,13 +1517,7 @@
|
||||
},
|
||||
"highlights_list_2": {
|
||||
"title": "Accentuations",
|
||||
"options": "Options",
|
||||
"title_with_count_one": "{{count}} mise en évidence",
|
||||
"title_with_count_many": "{{count}} mises en évidence",
|
||||
"title_with_count_other": "{{count}} mises en évidence",
|
||||
"modal_title": "Configurer les mises en évidence",
|
||||
"menu_configure": "Configuration des mises en évidence...",
|
||||
"no_highlights": "Aucune mise en évidence."
|
||||
"options": "Options"
|
||||
},
|
||||
"quick-search": {
|
||||
"placeholder": "Recherche rapide",
|
||||
@@ -1562,17 +1541,7 @@
|
||||
"create-child-note": "Créer une note enfant",
|
||||
"unhoist": "Désactiver le focus",
|
||||
"toggle-sidebar": "Basculer la barre latérale",
|
||||
"dropping-not-allowed": "Déplacer des notes à cet emplacement n'est pas autorisé.",
|
||||
"clone-indicator-tooltip": "Cette note a {{- count}} parents: {{- parents}}",
|
||||
"clone-indicator-tooltip-single": "Cette note est clonée (1 parent supplémentaire: {{- parent}})",
|
||||
"shared-indicator-tooltip": "Cette note est partagée publiquement",
|
||||
"shared-indicator-tooltip-with-url": "Cette note est partagée publiquement sur: {{- url}}",
|
||||
"subtree-hidden-tooltip_one": "{{count}} note enfant cachée de l'arbre",
|
||||
"subtree-hidden-tooltip_many": "{{count}} notes enfants cachées de l'arbre",
|
||||
"subtree-hidden-tooltip_other": "{{count}} notes enfants cachées de l'arbre",
|
||||
"subtree-hidden-moved-title": "Ajouté à {{title}}",
|
||||
"subtree-hidden-moved-description-collection": "Cette collection cache ses notes enfants dans l'arbre.",
|
||||
"subtree-hidden-moved-description-other": "Les notes enfants sont cachées dans l'arbre pour cette note."
|
||||
"dropping-not-allowed": "Lâcher des notes à cet endroit n'est pas autorisé"
|
||||
},
|
||||
"title_bar_buttons": {
|
||||
"window-on-top": "Épingler cette fenêtre au premier plan"
|
||||
@@ -1583,12 +1552,7 @@
|
||||
"printing_pdf": "Export au format PDF en cours...",
|
||||
"print_report_title": "Imprimer le rapport",
|
||||
"print_report_collection_details_button": "Consulter les détails",
|
||||
"print_report_collection_details_ignored_notes": "Notes ignorées",
|
||||
"print_report_error_title": "Échec de l'impression",
|
||||
"print_report_stack_trace": "Trace de la pile",
|
||||
"print_report_collection_content_one": "La {{count}} note de la collection n'a pas pu être imprimée car elle n'est pas prises en charge ou est protégée.",
|
||||
"print_report_collection_content_many": "Les {{count}} notes de la collection n'ont pas pu être imprimées car elles ne sont pas prises en charge ou sont protégées.",
|
||||
"print_report_collection_content_other": "Les {{count}} notes de la collection n'ont pas pu être imprimées car elles ne sont pas prises en charge ou sont protégées."
|
||||
"print_report_collection_details_ignored_notes": "Notes ignorées"
|
||||
},
|
||||
"note_title": {
|
||||
"placeholder": "saisir le titre de la note ici...",
|
||||
@@ -1597,24 +1561,17 @@
|
||||
"note_type_switcher_label": "Basculer de {{type}} à :",
|
||||
"note_type_switcher_others": "Autre type de note",
|
||||
"note_type_switcher_templates": "Modèle",
|
||||
"note_type_switcher_collection": "Collection",
|
||||
"edited_notes": "Notes éditées ce jour",
|
||||
"promoted_attributes": "Attributs promus"
|
||||
"note_type_switcher_collection": "Collection"
|
||||
},
|
||||
"search_result": {
|
||||
"no_notes_found": "Aucune note n'a été trouvée pour les paramètres de recherche donnés.",
|
||||
"search_not_executed": "La recherche n'a pas encore été exécutée.",
|
||||
"search_now": "Recherche maintenant"
|
||||
"search_not_executed": "La recherche n'a pas encore été exécutée. Cliquez sur le bouton \"Rechercher\" ci-dessus pour voir les résultats."
|
||||
},
|
||||
"spacer": {
|
||||
"configure_launchbar": "Configurer la Barre de raccourcis"
|
||||
},
|
||||
"sql_result": {
|
||||
"no_rows": "Aucune ligne n'a été renvoyée pour cette requête",
|
||||
"not_executed": "La requête n'a pas encore été exécutée.",
|
||||
"failed": "L'exécution de requêtes SQL a échoué",
|
||||
"statement_result": "Résultat de la déclaration",
|
||||
"execute_now": "Exécuter maintenant"
|
||||
"no_rows": "Aucune ligne n'a été renvoyée pour cette requête"
|
||||
},
|
||||
"sql_table_schemas": {
|
||||
"tables": "Tableaux"
|
||||
@@ -1737,7 +1694,7 @@
|
||||
"paste": "Coller",
|
||||
"paste-as-plain-text": "Coller comme texte brut",
|
||||
"search_online": "Rechercher «{{term}}» avec {{searchEngine}}",
|
||||
"search_in_trilium": "Rechercher « {{term}} » dans Trilium"
|
||||
"search_in_trilium": "Rechercher \"{{term}}\" dans Trilium"
|
||||
},
|
||||
"image_context_menu": {
|
||||
"copy_reference_to_clipboard": "Copier la référence dans le presse-papiers",
|
||||
@@ -1747,15 +1704,14 @@
|
||||
"open_note_in_new_tab": "Ouvrir la note dans un nouvel onglet",
|
||||
"open_note_in_new_split": "Ouvrir la note dans une nouvelle division",
|
||||
"open_note_in_new_window": "Ouvrir la note dans une nouvelle fenêtre",
|
||||
"open_note_in_popup": "Édition rapide",
|
||||
"open_note_in_other_split": "Ouvrir la note dans l'autre volet"
|
||||
"open_note_in_popup": "Édition rapide"
|
||||
},
|
||||
"electron_integration": {
|
||||
"desktop-application": "Application de bureau",
|
||||
"native-title-bar": "Barre de titre native",
|
||||
"native-title-bar-description": "Sous Windows et macOS, désactiver la barre de titre native rend l'application plus compacte. Sous Linux, le maintien de la barre de titre native permet une meilleure intégration avec le reste du système.",
|
||||
"background-effects": "Activer les effets d'arrière-plan",
|
||||
"background-effects-description": "Ajoute un arrière-plan flou et élégant aux fenêtres d'application, créant de la profondeur et un style moderne. La « barre de titre native » doit être désactivée.",
|
||||
"background-effects": "Activer les effets d'arrière-plan (Windows 11 uniquement)",
|
||||
"background-effects-description": "L'effet Mica ajoute un fond flou et élégant aux fenêtres de l'application, créant une profondeur et un style moderne.",
|
||||
"restart-app-button": "Redémarrez l'application pour afficher les modifications",
|
||||
"zoom-factor": "Facteur de zoom"
|
||||
},
|
||||
@@ -1774,8 +1730,7 @@
|
||||
"geo-map": {
|
||||
"create-child-note-title": "Créer une nouvelle note enfant et l'ajouter à la carte",
|
||||
"create-child-note-instruction": "Cliquez sur la carte pour créer une nouvelle note à cet endroit ou appuyez sur Échap pour la supprimer.",
|
||||
"unable-to-load-map": "Impossible de charger la carte.",
|
||||
"create-child-note-text": "Ajouter le marqueur"
|
||||
"unable-to-load-map": "Impossible de charger la carte."
|
||||
},
|
||||
"geo-map-context": {
|
||||
"open-location": "Ouvrir la position",
|
||||
@@ -1880,13 +1835,12 @@
|
||||
"book_properties_config": {
|
||||
"hide-weekends": "Masquer les week-ends",
|
||||
"display-week-numbers": "Afficher les numéros de semaine",
|
||||
"map-style": "Style de carte",
|
||||
"map-style": "Style de carte :",
|
||||
"max-nesting-depth": "Profondeur d'imbrication maximale :",
|
||||
"raster": "Trame",
|
||||
"vector_light": "Vecteur (clair)",
|
||||
"vector_dark": "Vecteur (foncé)",
|
||||
"show-scale": "Afficher l'échelle",
|
||||
"show-labels": "Afficher les noms des marqueurs"
|
||||
"show-scale": "Afficher l'échelle"
|
||||
},
|
||||
"table_context_menu": {
|
||||
"delete_row": "Supprimer la ligne"
|
||||
@@ -1907,7 +1861,7 @@
|
||||
"add-column-placeholder": "Entrez le nom de la colonne...",
|
||||
"edit-note-title": "Cliquez pour modifier le titre de la note",
|
||||
"edit-column-title": "Cliquez pour modifier le titre de la colonne",
|
||||
"column-already-exists": "Cette colonne existe déjà sur le tableau."
|
||||
"column-already-exists": "Cette colonne existe déjà dans le tableau."
|
||||
},
|
||||
"presentation_view": {
|
||||
"edit-slide": "Modifier cette diapositive",
|
||||
@@ -1937,30 +1891,22 @@
|
||||
"next_theme_message": "Vous utilisez actuellement le thème hérité de l'ancienne version, souhaitez-vous essayer le nouveau thème ?",
|
||||
"next_theme_button": "Essayez le nouveau thème",
|
||||
"background_effects_title": "Les effets d'arrière-plan sont désormais stables",
|
||||
"background_effects_message": "Sur les appareils Windows et macOS les effets d'arrière-plan sont désormais stables. Ils ajoutent une touche de couleur à l'interface utilisateur en floutant l'arrière-plan.",
|
||||
"background_effects_message": "Sur les appareils Windows, les effets d'arrière-plan sont désormais parfaitement stables. Ils ajoutent une touche de couleur à l'interface utilisateur en floutant l'arrière-plan. Cette technique est également utilisée dans d'autres applications comme l'Explorateur Windows.",
|
||||
"background_effects_button": "Activer les effets d'arrière-plan",
|
||||
"dismiss": "Rejeter",
|
||||
"new_layout_title": "Nouvelle mise en page",
|
||||
"new_layout_message": "Nous avons introduit une mise en page modernisée pour Trilium. Le ruban a été supprimé et intégré de manière transparente dans l'interface principale, avec une nouvelle barre d'état et des sections extensibles (telles que les attributs promus) reprenant les fonctions clés.\n\nLa nouvelle mise en page est activée par défaut et peut être temporairement désactivée via Options → Apparence.",
|
||||
"new_layout_button": "Plus d'infos"
|
||||
"dismiss": "Rejeter"
|
||||
},
|
||||
"settings": {
|
||||
"related_settings": "Paramètres associés"
|
||||
},
|
||||
"settings_appearance": {
|
||||
"related_code_blocks": "Schéma de coloration syntaxique pour les blocs de code dans les notes de texte",
|
||||
"related_code_notes": "Schéma de couleurs pour les notes de code",
|
||||
"ui": "Interface utilisateur",
|
||||
"ui_old_layout": "Ancienne mise en page",
|
||||
"ui_new_layout": "Nouvelle mise en page"
|
||||
"related_code_notes": "Schéma de couleurs pour les notes de code"
|
||||
},
|
||||
"units": {
|
||||
"percentage": "%"
|
||||
},
|
||||
"pagination": {
|
||||
"total_notes": "{{count}} notes",
|
||||
"prev_page": "Page précédente",
|
||||
"next_page": "Page suivante"
|
||||
"total_notes": "{{count}} notes"
|
||||
},
|
||||
"collections": {
|
||||
"rendering_error": "Impossible d'afficher le contenu en raison d'une erreur."
|
||||
@@ -1979,9 +1925,8 @@
|
||||
"unknown_widget": "Widget inconnu pour « {{id}} »."
|
||||
},
|
||||
"note_language": {
|
||||
"not_set": "Langage non défini",
|
||||
"configure-languages": "Configurer les langues...",
|
||||
"help-on-languages": "Aide sur les langues de contenu..."
|
||||
"not_set": "Non défini",
|
||||
"configure-languages": "Configurer les langues..."
|
||||
},
|
||||
"content_language": {
|
||||
"title": "Contenu des langues",
|
||||
@@ -2029,288 +1974,14 @@
|
||||
"title": "Options expérimentales",
|
||||
"disclaimer": "Ces options sont expérimentales et peuvent provoquer une instabilité. Utilisez avec prudence.",
|
||||
"new_layout_name": "Nouvelle mise en page",
|
||||
"new_layout_description": "Essayez la nouvelle mise en page pour un look plus moderne et un usage améliorée. Sous réserve de changements importants dans les prochaines versions.",
|
||||
"llm_name": "AI / LLM Chat",
|
||||
"llm_description": "Activer la barre de chat AI et les notes de chat LLM alimentées par de grands modèles de langage."
|
||||
"new_layout_description": "Essayez la nouvelle mise en page pour un look plus moderne et un usage améliorée. Sous réserve de changements importants dans les prochaines versions."
|
||||
},
|
||||
"read-only-info": {
|
||||
"read-only-note": "Vous consultez actuellement une note en lecture seule.",
|
||||
"auto-read-only-note": "Cette note s'affiche en mode lecture seule pour un chargement plus rapide.",
|
||||
"edit-note": "Modifier la note"
|
||||
"edit-note": "Editer la note"
|
||||
},
|
||||
"calendar_view": {
|
||||
"delete_note": "Supprimer la note..."
|
||||
},
|
||||
"media": {
|
||||
"play": "Lire (Espace)",
|
||||
"pause": "Pause (Espace)",
|
||||
"back-10s": "Retour arrière 10s (flèche gauche)",
|
||||
"forward-30s": "Avance 30s",
|
||||
"mute": "Silence (M)",
|
||||
"unmute": "Réactiver le son (M)",
|
||||
"playback-speed": "Vitesse de lecture",
|
||||
"loop": "Boucle",
|
||||
"disable-loop": "Désactiver la boucle",
|
||||
"rotate": "Rotation",
|
||||
"picture-in-picture": "Image dans l'image",
|
||||
"exit-picture-in-picture": "Sortir de Image dans l'image",
|
||||
"fullscreen": "Plein-écran (F)",
|
||||
"exit-fullscreen": "Sortir du mode plein-écran",
|
||||
"unsupported-format": "L'aperçu multimédia n'est pas disponible pour ce format de fichier:\n{{mime}}",
|
||||
"zoom-to-fit": "Zoom pour remplir",
|
||||
"zoom-reset": "Annuler zoom pour remplir"
|
||||
},
|
||||
"render": {
|
||||
"setup_title": "Afficher du HTML personnalisé ou Preact JSX dans cette note",
|
||||
"setup_create_sample_preact": "Créer un exemple de note avec Preact",
|
||||
"setup_create_sample_html": "Créer un exemple de note avec HTML",
|
||||
"setup_sample_created": "Un exemple de note a été créé en tant que note enfant.",
|
||||
"disabled_description": "Ces notes de rendu proviennent d'une source externe. Pour vous protéger de contenu malveillant, elle n'est pas activée par défaut. Assurez-vous de faire confiance à la source avant de l’activer.",
|
||||
"disabled_button_enable": "Activer la note de rendu"
|
||||
},
|
||||
"web_view_setup": {
|
||||
"title": "Créez la vue de la page Web directement dans Trilium",
|
||||
"url_placeholder": "Entrez ou collez l'adresse du site Web, par exemple https://triliumnotes.org",
|
||||
"create_button": "Créer une vue Web",
|
||||
"invalid_url_title": "Adresse invalide",
|
||||
"invalid_url_message": "Insérer une adresse Web valide, par exemple https://triliumnotes.org.",
|
||||
"disabled_description": "Cette vue Web a été importée à partir d'une source externe. Pour vous protéger du phishing ou du contenu malveillant, elle ne se charge pas automatiquement. Vous pouvez l'activer si vous faites confiance à la source.",
|
||||
"disabled_button_enable": "Activer la vue Web"
|
||||
},
|
||||
"llm_chat": {
|
||||
"placeholder": "Tapez un message...",
|
||||
"send": "Envoyer",
|
||||
"sending": "Envoi...",
|
||||
"empty_state": "Démarrez une conversation en tapant un message ci-dessous.",
|
||||
"searching_web": "Recherche sur le Web...",
|
||||
"web_search": "Recherche sur le Web",
|
||||
"note_tools": "Accès aux notes",
|
||||
"sources": "Sources",
|
||||
"extended_thinking": "Réflexion étendue",
|
||||
"legacy_models": "Modèles hérités",
|
||||
"thinking": "Réflexion...",
|
||||
"thought_process": "Processus de réflexion",
|
||||
"tool_calls": "{{count}} appel(s) d'outil",
|
||||
"input": "Entrée",
|
||||
"result": "Résultat",
|
||||
"error": "Erreur",
|
||||
"tool_error": "échoué",
|
||||
"total_tokens": "{{total}} jetons",
|
||||
"tokens_detail": "{{prompt}} prompt + {{completion}} achèvement",
|
||||
"tokens_used": "{{prompt}} prompt + {{completion}} achèvement = {{total}} jetons",
|
||||
"tokens_used_with_cost": "{{prompt}} prompt + {{completion}} achèvement = {{total}} jetons (~${{cost}})",
|
||||
"tokens_used_with_model": "{{model}}: {{prompt}} prompt + {{completion}} achèvement = {{total}} jetons",
|
||||
"tokens_used_with_model_and_cost": "{{model}}: {{prompt}} prompt + {{completion}} achèvement = {{total}} jetons (~${{cost}})",
|
||||
"tokens": "jetons",
|
||||
"context_used": "{{percentage}}% utilisé",
|
||||
"note_context_enabled": "Cliquez pour désactiver le contexte de la note : {{title}}",
|
||||
"note_context_disabled": "Cliquez pour inclure la note actuelle dans le contexte",
|
||||
"no_provider_message": "Aucun fournisseur d'IA configuré. Ajoutez en un pour commencer à discuter.",
|
||||
"add_provider": "Ajouter un fournisseur d'IA"
|
||||
},
|
||||
"sidebar_chat": {
|
||||
"title": "discussion IA",
|
||||
"launcher_title": "Ouvrir la discussion IA",
|
||||
"new_chat": "Démarrer une nouvelle discussion",
|
||||
"save_chat": "Enregistrer la discussion dans les notes",
|
||||
"empty_state": "Démarrer une conversation",
|
||||
"history": "Historique des discussions",
|
||||
"recent_chats": "Discussions récentes",
|
||||
"no_chats": "Pas de discussions précédentes"
|
||||
},
|
||||
"note-color": {
|
||||
"clear-color": "Retirer la couleur de la note",
|
||||
"set-color": "Définir la couleur de la note",
|
||||
"set-custom-color": "Définir la couleur personnalisée de la note"
|
||||
},
|
||||
"popup-editor": {
|
||||
"maximize": "Basculer sur l'éditeur complet"
|
||||
},
|
||||
"server": {
|
||||
"unknown_http_error_title": "Erreur de communication avec le serveur",
|
||||
"unknown_http_error_content": "Code de statut: {{statusCode}}\nURL: {{method}} {{url}}\nMessage: {{message}}",
|
||||
"traefik_blocks_requests": "Si vous utilisez le reverse proxy Traefik, celui-ci a introduit un changement de rupture qui affecte la communication avec le serveur."
|
||||
},
|
||||
"tab_history_navigation_buttons": {
|
||||
"go-back": "Revenir à la note précédente",
|
||||
"go-forward": "Aller vers la note suivante"
|
||||
},
|
||||
"breadcrumb": {
|
||||
"hoisted_badge": "Remonté",
|
||||
"hoisted_badge_title": "Redescendu",
|
||||
"workspace_badge": "Espace de travail",
|
||||
"scroll_to_top_title": "Aller au début de la note",
|
||||
"create_new_note": "Créer une nouvelle note enfant",
|
||||
"empty_hide_archived_notes": "Cacher les notes archivées"
|
||||
},
|
||||
"breadcrumb_badges": {
|
||||
"read_only_explicit": "Lecture seule",
|
||||
"read_only_explicit_description": "Cette note a été paramétrée manuellement en lecture seule.\nCliquer pour temporairement l'éditer.",
|
||||
"read_only_auto": "Lecture seule automatique",
|
||||
"read_only_auto_description": "Cette note a été réglée automatiquement en mode lecture seule pour des raisons de performances. Cette limite automatique est réglable à partir des paramètres.\n\nCliquez pour la modifier temporairement.",
|
||||
"read_only_temporarily_disabled": "Temporairement modifiable",
|
||||
"read_only_temporarily_disabled_description": "Cette note est actuellement modifiable, mais elle est normalement en lecture seule. La note redeviendra en lecture seule dès que vous accéderez à une autre note.\n\nCliquez pour réactiver le mode lecture seule.",
|
||||
"shared_publicly": "Partagés publiquement",
|
||||
"shared_locally": "Partagé localement",
|
||||
"shared_copy_to_clipboard": "Copier le lien vers le presse-papier",
|
||||
"shared_open_in_browser": "Ouvrir le lien dans le navigateur",
|
||||
"shared_unshare": "Supprimer le partage",
|
||||
"clipped_note": "Clip Web",
|
||||
"clipped_note_description": "Cette note a été initialement construite depuis l'url {{url}}.\n\nCliquez pour accéder à la page Web source.",
|
||||
"execute_script": "Exécuter le script",
|
||||
"execute_script_description": "Cette note est une note de script. Cliquez pour exécuter le script.",
|
||||
"execute_sql": "Exécuter la commande SQL",
|
||||
"execute_sql_description": "Cette note est une note SQL. Cliquer pour exécuter la requête SQL.",
|
||||
"save_status_saved": "Enregister",
|
||||
"save_status_saving": "Enregistrement...",
|
||||
"save_status_unsaved": "Non sauvée",
|
||||
"save_status_error": "La sauvegarde a échoué",
|
||||
"save_status_saving_tooltip": "Les modifications sont enregistrées.",
|
||||
"save_status_unsaved_tooltip": "Il y a des changements non enregistrés. Ils seront enregistrés automatiquement dans un instant.",
|
||||
"save_status_error_tooltip": "Une erreur s'est produite lors de l'enregistrement de la note. Si possible, essayez de copier le contenu de la note ailleurs et de recharger l'application."
|
||||
},
|
||||
"right_pane": {
|
||||
"toggle": "Basculer le panneau de droite",
|
||||
"custom_widget_go_to_source": "Aller sur le code source",
|
||||
"empty_message": "Rien à afficher pour cette note",
|
||||
"empty_button": "Cacher le panneau"
|
||||
},
|
||||
"pdf": {
|
||||
"attachments_one": "{{count}} pièce jointe",
|
||||
"attachments_many": "{{count}} pièces jointes",
|
||||
"attachments_other": "{{count}} pièces jointes",
|
||||
"layers_one": "{{count}} couche",
|
||||
"layers_many": "{{count}} couches",
|
||||
"layers_other": "{{count}} couches",
|
||||
"pages_one": "{{count}} page",
|
||||
"pages_many": "{{count}} pages",
|
||||
"pages_other": "{{count}} pages",
|
||||
"pages_alt": "Page {{pageNumber}}",
|
||||
"pages_loading": "Chargement..."
|
||||
},
|
||||
"platform_indicator": {
|
||||
"available_on": "Disponible sur {{platform}}"
|
||||
},
|
||||
"mobile_tab_switcher": {
|
||||
"title_one": "{{count}} onglet",
|
||||
"title_many": "{{count}} onglets",
|
||||
"title_other": "{{count}} onglets",
|
||||
"more_options": "Autres options"
|
||||
},
|
||||
"bookmark_buttons": {
|
||||
"bookmarks": "Signets"
|
||||
},
|
||||
"active_content_badges": {
|
||||
"type_icon_pack": "pack d'icônes",
|
||||
"type_backend_script": "Script backend",
|
||||
"type_frontend_script": "Script frontend",
|
||||
"type_widget": "Widget",
|
||||
"type_app_css": "CSS personnalisé",
|
||||
"type_render_note": "Note de rendu",
|
||||
"type_web_view": "Vue Web",
|
||||
"type_app_theme": "Thème personnalisé",
|
||||
"toggle_tooltip_enable_tooltip": "Cliquer pour activer {{type}}.",
|
||||
"toggle_tooltip_disable_tooltip": "Cliquer pour désactiver ce {{type}}.",
|
||||
"menu_docs": "Ouvrir la documentation",
|
||||
"menu_execute_now": "Exécuter le script maintenant",
|
||||
"menu_run": "Démarrer automatiquement",
|
||||
"menu_run_disabled": "Manuellement",
|
||||
"menu_run_backend_startup": "Lorsque le backend commence",
|
||||
"menu_run_hourly": "Horaire",
|
||||
"menu_run_daily": "Quotidien",
|
||||
"menu_run_frontend_startup": "Lorsque le frontend du bureau démarre",
|
||||
"menu_run_mobile_startup": "Lorsque le frontend mobile démarre",
|
||||
"menu_change_to_widget": "Passer au widget",
|
||||
"menu_change_to_frontend_script": "Passer au script frontend",
|
||||
"menu_theme_base": "Thème de base"
|
||||
},
|
||||
"setup_form": {
|
||||
"more_info": "En savoir plus"
|
||||
},
|
||||
"mermaid": {
|
||||
"placeholder": "Tapez le contenu de votre diagramme Mermaid ou utilisez l'un des diagrammes de l'échantillon ci-dessous.",
|
||||
"sample_diagrams": "Diagrammes d 'exemple:",
|
||||
"sample_flowchart": "Organigramme",
|
||||
"sample_class": "Classe",
|
||||
"sample_sequence": "Séquence",
|
||||
"sample_entity_relationship": "Entité relationnelle",
|
||||
"sample_state": "État",
|
||||
"sample_mindmap": "Carte mentale",
|
||||
"sample_architecture": "Architecture",
|
||||
"sample_block": "Bloc",
|
||||
"sample_c4": "C4",
|
||||
"sample_gantt": "Gantt",
|
||||
"sample_git": "Git",
|
||||
"sample_kanban": "Kanban",
|
||||
"sample_packet": "Paquet",
|
||||
"sample_pie": "Camembert",
|
||||
"sample_quadrant": "Quadrant",
|
||||
"sample_radar": "Radar",
|
||||
"sample_requirement": "Exigence",
|
||||
"sample_sankey": "Sankey",
|
||||
"sample_timeline": "Chronologie",
|
||||
"sample_treemap": "Arborescence",
|
||||
"sample_user_journey": "Utilisateur Journey",
|
||||
"sample_xy": "XY",
|
||||
"sample_venn": "Venn",
|
||||
"sample_ishikawa": "Ishikawa"
|
||||
},
|
||||
"mind-map": {
|
||||
"addChild": "Ajouter un enfant",
|
||||
"addParent": "Ajouter parent",
|
||||
"addSibling": "Ajouter un frère",
|
||||
"removeNode": "Supprimer le nœud",
|
||||
"focus": "Mode Focus",
|
||||
"cancelFocus": "Annuler le mode Focus",
|
||||
"moveUp": "Monter",
|
||||
"moveDown": "Descendre",
|
||||
"link": "Lien",
|
||||
"linkBidirectional": "Lien bidirectionnel",
|
||||
"clickTips": "Cliquer sur le nœud cible",
|
||||
"summary": "Résumé"
|
||||
},
|
||||
"llm": {
|
||||
"settings_title": "AI / LLM",
|
||||
"settings_description": "Configurer les intégrations AI et les LLM (Large Language Model).",
|
||||
"add_provider": "Ajouter le fournisseur",
|
||||
"add_provider_title": "Ajouter le fournisseur d'IA",
|
||||
"configured_providers": "Fournisseurs configurés",
|
||||
"no_providers_configured": "Aucun fournisseur n'est encore configuré.",
|
||||
"provider_name": "Nom",
|
||||
"provider_type": "Fournisseur",
|
||||
"actions": "Actions",
|
||||
"delete_provider": "Supprimer",
|
||||
"delete_provider_confirmation": "Êtes-vous sûr de vouloir supprimer le fournisseur \"{{name}}\" ?",
|
||||
"api_key": "Clé API",
|
||||
"api_key_placeholder": "Entrer votre clé API",
|
||||
"cancel": "Annuler"
|
||||
},
|
||||
"status_bar": {
|
||||
"language_title": "Changer de langue",
|
||||
"note_info_title": "Afficher les informations sur les notes (par exemple, dates, taille des notes)",
|
||||
"backlinks_one": "{{count}} rétrolien",
|
||||
"backlinks_many": "{{count}} rétroliens",
|
||||
"backlinks_other": "{{count}} rétroliens",
|
||||
"backlinks_title_one": "voir le rétrolien",
|
||||
"backlinks_title_many": "voir les rétroliens",
|
||||
"backlinks_title_other": "voir les rétroliens",
|
||||
"attachments_one": "{{count}} pièce-jointe",
|
||||
"attachments_many": "{{count}} pièces-jointes",
|
||||
"attachments_other": "{{count}} pièces-jointes",
|
||||
"attachments_title_one": "Voir la pièce-jointe dans un nouvel onglet",
|
||||
"attachments_title_many": "Voir les pièces-jointes dans un nouvel onglet",
|
||||
"attachments_title_other": "Voir les pièces-jointes dans un nouvel onglet",
|
||||
"attributes_one": "{{count}} attribut",
|
||||
"attributes_many": "{{count}} attributs",
|
||||
"attributes_other": "{{count}} attributs",
|
||||
"attributes_title": "Attributs propres et attributs hérités",
|
||||
"note_paths_one": "{{count}} chemin",
|
||||
"note_paths_many": "{{count}} chemins",
|
||||
"note_paths_other": "{{count}} chemins",
|
||||
"note_paths_title": "Chemins de la note",
|
||||
"code_note_switcher": "Changer de langue"
|
||||
},
|
||||
"attributes_panel": {
|
||||
"title": "Attributs de la note"
|
||||
"delete_note": "Effacer la note..."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,6 +119,7 @@
|
||||
"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.",
|
||||
@@ -126,7 +127,9 @@
|
||||
"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"
|
||||
"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",
|
||||
@@ -396,7 +399,7 @@
|
||||
"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<ul>\n<li>frontendStartup - nuair a thosaíonn (nó a athnuachan) tosaigh Trilium, ach ní ar fhóin phóca.</li>\n<li>mobileStartup - nuair a thosaíonn (nó a athnuachan) tosaigh Trilium, ar fhóin phóca.</li>\n<li>backendStartup - nuair a thosaíonn cúltaca Trilium.</li>\n<li>hourly - rith uair san uair. Is féidir leat lipéad breise <code>runAtHour</code> a úsáid chun a shonrú cén uair a ritheann sé.</li>\n<li>daily - rith uair sa lá.</li>\n</ul>",
|
||||
"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<ul>\n<li>frontendStartup - nuair a thosaíonn (nó a athnuachan) tosaigh Trilium, ach ní ar fhóin phóca.</li>\n<li>mobileStartup - nuair a thosaíonn (nó a athnuachan) tosaigh Trilium, ar fhóin phóca.</li>\n<li>backendStartup - nuair a thosaíonn cúltaca Trilium</li>\n<li>uair an chloig - rith uair san uair. Is féidir leat lipéad breise <code>runAtHour</code> a úsáid chun a shonrú cén uair a ritheann sé.</li>\n<li>daily - rith uair sa lá</li>\n</ul>",
|
||||
"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 <code>#run=hourly</code>. 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.",
|
||||
@@ -474,8 +477,7 @@
|
||||
"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: <code>A0</code>, <code>A1</code>, <code>A2</code>, <code>A3</code>, <code>A4</code>, <code>A5</code>, <code>A6</code>, <code>Legal</code>, <code>Letter</code>, <code>Tabloid</code>, <code>Ledger</code>.",
|
||||
"color_type": "Dath",
|
||||
"textarea": "Téacs Il-líne"
|
||||
"color_type": "Dath"
|
||||
},
|
||||
"attribute_editor": {
|
||||
"help_text_body1": "Chun lipéad a chur leis, clóscríobh m.sh. <code>#rock</code> nó más mian leat luach a chur leis freisin ansin m.sh. <code>#year = 2020</code>",
|
||||
@@ -706,8 +708,7 @@
|
||||
"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í",
|
||||
"view_ocr_text": "Féach ar théacs OCR"
|
||||
"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}}'"
|
||||
@@ -1054,6 +1055,7 @@
|
||||
"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",
|
||||
@@ -1068,8 +1070,7 @@
|
||||
"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",
|
||||
"rename_relation": "Athainmnigh an gaol"
|
||||
"click_on_canvas_to_place_new_note": "Cliceáil ar chanbhás chun nóta nua a chur"
|
||||
},
|
||||
"backend_log": {
|
||||
"refresh": "Athnuachan"
|
||||
@@ -1126,9 +1127,7 @@
|
||||
"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.",
|
||||
"llm_name": "Comhrá AI / LLM",
|
||||
"llm_description": "Cumasaigh an taobhbharra comhrá AI agus nótaí comhrá LLM faoi thiomáint ag samhlacha teanga móra."
|
||||
"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",
|
||||
@@ -1223,28 +1222,12 @@
|
||||
},
|
||||
"images": {
|
||||
"images_section_title": "Íomhánna",
|
||||
"download_images_automatically": "Íomhánna a íoslódáil go huathoibríoch",
|
||||
"download_images_description": "Íoslódáil íomhánna tagartha ar líne ó HTML greamaithe ionas go mbeidh siad ar fáil as líne.",
|
||||
"enable_image_compression": "Comhbhrú íomhá",
|
||||
"max_image_dimensions": "Uasmhéid toisí íomhá",
|
||||
"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": "Is é an raon molta ná 50–85. Laghdaíonn luachanna níos ísle méid an chomhaid, agus coinníonn luachanna níos airde sonraí.",
|
||||
"enable_image_compression_description": "Comhbhrúigh agus athraigh méid íomhánna nuair a uaslódálfar nó a ghreamaítear iad.",
|
||||
"max_image_dimensions_description": "Athrófar méid íomhánna a sháraíonn an méid seo go huathoibríoch.",
|
||||
"jpeg_quality": "Cáilíocht JPEG",
|
||||
"ocr_section_title": "Eastóscadh Téacs (OCR)",
|
||||
"ocr_related_content_languages": "Teangacha ábhair (a úsáidtear le haghaidh eastóscadh téacs)",
|
||||
"ocr_auto_process": "Próiseáil comhaid nua go huathoibríoch",
|
||||
"ocr_auto_process_description": "Bain téacs go huathoibríoch as comhaid atá uaslódáilte nó greamaithe le déanaí.",
|
||||
"ocr_min_confidence": "Íosmhuinín",
|
||||
"ocr_confidence_description": "Ná bain ach téacs os cionn an tairsí muiníne seo. Cuimsíonn luachanna níos ísle níos mó téacs ach d'fhéadfadh siad a bheith níos lú cruinn.",
|
||||
"batch_ocr_title": "Próiseáil Comhaid atá ann cheana",
|
||||
"batch_ocr_description": "Bain téacs as na híomhánna, na PDFanna agus na doiciméid Office go léir atá i do nótaí. D’fhéadfadh sé seo roinnt ama a thógáil ag brath ar líon na gcomhad.",
|
||||
"batch_ocr_start": "Tosaigh Próiseáil Bhaisc",
|
||||
"batch_ocr_starting": "Ag tosú próiseáil bhaisc...",
|
||||
"batch_ocr_progress": "Ag próiseáil {{processed}} de {{total}} comhad...",
|
||||
"batch_ocr_completed": "Próiseáil bhaisc críochnaithe! Próiseáladh {{processed}} comhad.",
|
||||
"batch_ocr_error": "Earráid le linn próiseála baisce: {{error}}"
|
||||
"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",
|
||||
@@ -1290,7 +1273,7 @@
|
||||
"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",
|
||||
"custom_url_placeholder": "Saincheap url an innill chuardaigh",
|
||||
"save_button": "Sábháil"
|
||||
},
|
||||
"tray": {
|
||||
@@ -1466,20 +1449,18 @@
|
||||
"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": "Seiceáil litriú",
|
||||
"language_code_label": "Seiceáil Litrithe Teangacha",
|
||||
"restart-required": "Tiocfaidh athruithe ar na roghanna seiceála litrithe i bhfeidhm tar éis atosú an fheidhmchláir.",
|
||||
"custom_dictionary_title": "Foclóir Saincheaptha",
|
||||
"custom_dictionary_description": "Déantar focail a chuirtear leis an bhfoclóir a sioncrónú ar fud do ghléasanna go léir.",
|
||||
"custom_dictionary_edit": "Focail saincheaptha",
|
||||
"custom_dictionary_edit_description": "Cuir an liosta focal in eagar nach ceart don seiceálaí litrithe a mharcáil. Beidh athruithe le feiceáil tar éis atosaithe.",
|
||||
"custom_dictionary_open": "Cuir an foclóir in eagar",
|
||||
"related_description": "Cumraigh teangacha seiceála litrithe agus foclóir saincheaptha."
|
||||
"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).",
|
||||
@@ -1591,8 +1572,7 @@
|
||||
"task-list": "Liosta Tascanna",
|
||||
"new-feature": "Nua",
|
||||
"collections": "Bailiúcháin",
|
||||
"spreadsheet": "Scarbhileog",
|
||||
"llm-chat": "Comhrá AI"
|
||||
"spreadsheet": "Scarbhileog"
|
||||
},
|
||||
"protect_note": {
|
||||
"toggle-on": "Cosain an nóta",
|
||||
@@ -1920,7 +1900,7 @@
|
||||
},
|
||||
"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. Ceadaíonn sé seo gnéithe ar nós seiceáil litrithe, tacaíocht ó dheis go clé agus eastóscadh téacs (OCR)."
|
||||
"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",
|
||||
@@ -2248,167 +2228,5 @@
|
||||
},
|
||||
"setup_form": {
|
||||
"more_info": "Foghlaim níos mó"
|
||||
},
|
||||
"media": {
|
||||
"play": "Seinn (Spás)",
|
||||
"pause": "Sos (Spás)",
|
||||
"back-10s": "10 soicind ar ais (eochair saighead chlé)",
|
||||
"forward-30s": "Ar aghaidh 30s",
|
||||
"mute": "Balbhaigh (M)",
|
||||
"unmute": "Díbhalbhaigh (M)",
|
||||
"playback-speed": "Luas athsheinm",
|
||||
"loop": "Lúb",
|
||||
"disable-loop": "Díchumasaigh an lúb",
|
||||
"rotate": "Rothlaigh",
|
||||
"picture-in-picture": "Pictiúr i bpictiúr",
|
||||
"exit-picture-in-picture": "Scoir pictiúr-i-bpictiúr",
|
||||
"fullscreen": "Lánscáileán (F)",
|
||||
"exit-fullscreen": "Scoir lánscáileáin",
|
||||
"unsupported-format": "Níl réamhamharc meán ar fáil don fhormáid comhaid seo:\n{{mime}}",
|
||||
"zoom-to-fit": "Zúmáil chun líonadh",
|
||||
"zoom-reset": "Athshocraigh súmáil chun líonadh"
|
||||
},
|
||||
"mermaid": {
|
||||
"placeholder": "Clóscríobh ábhar do léaráid Maighdean Mhara nó bain úsáid as ceann de na léaráidí samplacha thíos.",
|
||||
"sample_diagrams": "Léaráidí samplacha:",
|
||||
"sample_flowchart": "Cairt Sreabhadh",
|
||||
"sample_class": "Rang",
|
||||
"sample_sequence": "Seicheamh",
|
||||
"sample_entity_relationship": "Gaol Eintitis",
|
||||
"sample_state": "Stát",
|
||||
"sample_mindmap": "Léarscáil intinne",
|
||||
"sample_architecture": "Ailtireacht",
|
||||
"sample_block": "Bloc",
|
||||
"sample_c4": "C4",
|
||||
"sample_gantt": "Gantt",
|
||||
"sample_git": "Git",
|
||||
"sample_kanban": "Kanban",
|
||||
"sample_packet": "Paicéad",
|
||||
"sample_pie": "Pióg",
|
||||
"sample_quadrant": "Ceathrú",
|
||||
"sample_radar": "Radar",
|
||||
"sample_requirement": "Riachtanas",
|
||||
"sample_sankey": "Sankey",
|
||||
"sample_timeline": "Amlíne",
|
||||
"sample_treemap": "Léarscáil Crann",
|
||||
"sample_user_journey": "Turas Úsáideora",
|
||||
"sample_xy": "XY",
|
||||
"sample_venn": "Venn",
|
||||
"sample_ishikawa": "Ishikawa",
|
||||
"sample_treeview": "Radharc Crann",
|
||||
"sample_wardley": "Léarscáil Wardley"
|
||||
},
|
||||
"llm_chat": {
|
||||
"placeholder": "Clóscríobh teachtaireacht...",
|
||||
"send": "Seol",
|
||||
"sending": "Ag seoladh...",
|
||||
"empty_state": "Tosaigh comhrá trí theachtaireacht a chlóscríobh thíos.",
|
||||
"searching_web": "Ag cuardach an ghréasáin...",
|
||||
"web_search": "Cuardach gréasáin",
|
||||
"note_tools": "Rochtain nótaí",
|
||||
"sources": "Foinsí",
|
||||
"extended_thinking": "Smaointeoireacht leathnaithe",
|
||||
"legacy_models": "Samhlacha oidhreachta",
|
||||
"thinking": "Ag smaoineamh...",
|
||||
"thought_process": "Próiseas smaointeoireachta",
|
||||
"tool_calls": "{{count}} glao(í) uirlisí",
|
||||
"input": "Ionchur",
|
||||
"result": "Toradh",
|
||||
"error": "Earráid",
|
||||
"tool_error": "theip",
|
||||
"total_tokens": "{{total}} comharthaí",
|
||||
"tokens_detail": "leid {{prompt}} + críochnú {{completion}}",
|
||||
"tokens_used": "{{prompt}} leid + {{completion}} críochnú = {{total}} comharthaí",
|
||||
"tokens_used_with_cost": "{{prompt}} leid + {{completion}} críochnú = {{total}} comharthaí (~${{cost}})",
|
||||
"tokens_used_with_model": "{{model}}: {{prompt}} leid + {{completion}} críochnú = {{total}} comharthaí",
|
||||
"tokens_used_with_model_and_cost": "{{model}}: leid {{prompt}} + críochnú {{completion}} = {{total}} comharthaí (~${{cost}})",
|
||||
"tokens": "comharthaí",
|
||||
"context_used": "Úsáideadh {{percentage}}%",
|
||||
"note_context_enabled": "Cliceáil chun comhthéacs nótaí a dhíchumasú: {{title}}",
|
||||
"note_context_disabled": "Cliceáil chun an nóta reatha a chur san áireamh i gcomhthéacs",
|
||||
"no_provider_message": "Níl aon soláthraí AI cumraithe. Cuir ceann leis chun comhrá a thosú.",
|
||||
"add_provider": "Cuir Soláthraí AI leis",
|
||||
"sources_summary": "{{count}} foinsí ó {{sites}} suíomhanna"
|
||||
},
|
||||
"sidebar_chat": {
|
||||
"title": "Comhrá AI",
|
||||
"launcher_title": "Oscail Comhrá AI",
|
||||
"new_chat": "Tosaigh comhrá nua",
|
||||
"save_chat": "Sábháil comhrá sna nótaí",
|
||||
"empty_state": "Tosaigh comhrá",
|
||||
"history": "Stair chomhrá",
|
||||
"recent_chats": "Comhráite le déanaí",
|
||||
"no_chats": "Gan aon chomhráite roimhe seo"
|
||||
},
|
||||
"mind-map": {
|
||||
"addChild": "Cuir páiste leis",
|
||||
"addParent": "Cuir tuismitheoir leis",
|
||||
"addSibling": "Cuir deartháir nó deirfiúr leis",
|
||||
"removeNode": "Bain nód",
|
||||
"focus": "Mód Fócais",
|
||||
"cancelFocus": "Cealaigh Mód Fócais",
|
||||
"moveUp": "Bog suas",
|
||||
"moveDown": "Bog síos",
|
||||
"link": "Nasc",
|
||||
"linkBidirectional": "Nasc Déthreoch",
|
||||
"clickTips": "Cliceáil ar an nód sprice le do thoil",
|
||||
"summary": "Achoimre"
|
||||
},
|
||||
"llm": {
|
||||
"settings_title": "AI / LLM",
|
||||
"settings_description": "Cumraigh comhtháthú idir Intleacht Shaorga agus Múnla Teanga Mór.",
|
||||
"add_provider": "Cuir Soláthraí leis",
|
||||
"add_provider_title": "Cuir Soláthraí AI leis",
|
||||
"configured_providers": "Soláthraithe Cumraithe",
|
||||
"no_providers_configured": "Níl aon soláthraithe cumraithe fós.",
|
||||
"provider_name": "Ainm",
|
||||
"provider_type": "Soláthraí",
|
||||
"actions": "Gníomhartha",
|
||||
"delete_provider": "Scrios",
|
||||
"delete_provider_confirmation": "An bhfuil tú cinnte gur mian leat an soláthraí \"{{name}}\" a scriosadh?",
|
||||
"api_key": "Eochair API",
|
||||
"api_key_placeholder": "Cuir isteach d'eochair API",
|
||||
"cancel": "Cealaigh",
|
||||
"feature_not_enabled": "Cumasaigh an ghné turgnamhach LLM i Socruithe → Ardleibhéil → Gnéithe turgnamhacha chun comhtháthú AI a úsáid.",
|
||||
"mcp_title": "MCP (Prótacal Comhthéacs Múnla)",
|
||||
"mcp_enabled": "Freastalaí MCP",
|
||||
"mcp_enabled_description": "Nochtaigh críochphointe Prótacal Comhthéacs Múnla (MCP) ionas gur féidir le cúntóirí códaithe AI (m.sh. Claude Code, GitHub Copilot) do nótaí a léamh agus a mhodhnú. Ní féidir rochtain a fháil ar an gcríochphointe ach ó localhost.",
|
||||
"mcp_endpoint_title": "URL críochphointe",
|
||||
"mcp_endpoint_description": "Cuir an URL seo le cumraíocht MCP do chúntóra AI",
|
||||
"tools": {
|
||||
"search_notes": "Cuardaigh nótaí",
|
||||
"get_note": "Faigh nóta",
|
||||
"get_note_content": "Faigh ábhar nótaí",
|
||||
"update_note_content": "Nuashonraigh ábhar an nóta",
|
||||
"append_to_note": "Cuir leis an nóta",
|
||||
"create_note": "Cruthaigh nóta",
|
||||
"get_attributes": "Faigh tréithe",
|
||||
"get_attribute": "Faigh tréith",
|
||||
"set_attribute": "Socraigh tréith",
|
||||
"delete_attribute": "Scrios tréith",
|
||||
"get_child_notes": "Faigh nótaí leanaí",
|
||||
"get_subtree": "Faigh fo-chrann",
|
||||
"load_skill": "Luchtaigh scileanna",
|
||||
"web_search": "Cuardach gréasáin",
|
||||
"note_in_parent": "<Note/> i <Parent/>",
|
||||
"get_attachment": "Faigh ceangaltán",
|
||||
"get_attachment_content": "Léigh ábhar an cheangail"
|
||||
}
|
||||
},
|
||||
"ocr": {
|
||||
"extracted_text": "Téacs Bainte (OCR)",
|
||||
"extracted_text_title": "Téacs Bainte (OCR)",
|
||||
"loading_text": "Ag lódáil téacs OCR...",
|
||||
"no_text_available": "Níl aon téacs OCR ar fáil",
|
||||
"no_text_explanation": "Níor próiseáladh an nóta seo le haghaidh eastóscadh téacs OCR nó níor aimsíodh aon téacs.",
|
||||
"failed_to_load": "Theip ar lódáil téacs OCR",
|
||||
"process_now": "Próiseas OCR",
|
||||
"processing": "Ag próiseáil...",
|
||||
"processing_started": "Tá próiseáil OCR tosaithe. Fan nóiméad agus athnuachan le do thoil.",
|
||||
"processing_failed": "Theip ar phróiseáil OCR a thosú",
|
||||
"view_extracted_text": "Féach ar théacs eastósctha (OCR)",
|
||||
"processing_complete": "Próiseáil OCR críochnaithe.",
|
||||
"text_filtered_low_confidence": "Bhraith OCR téacs le muinín {{confidence}}%, ach caitheadh leis é mar is é {{threshold}}% an tairseach íosta atá agat.",
|
||||
"open_media_settings": "Oscail Socruithe"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,6 +94,7 @@
|
||||
"if_you_dont_check": "अगर आप इसे चेक नहीं करते हैं, तो नोट केवल रिलेशन मैप से हटाया जाएगा।"
|
||||
},
|
||||
"delete_notes": {
|
||||
"delete_notes_preview": "नोट्स प्रिव्यू डिलीट करें",
|
||||
"close": "बंद करें",
|
||||
"delete_all_clones_description": "सभी क्लोन भी डिलीट करें (हाल के बदलावों में वापस ला सकते हैं)",
|
||||
"erase_notes_description": "सामान्य (सॉफ्ट) डिलीट करने पर नोट केवल 'डिलीटेड' मार्क होते हैं और उन्हें एक निश्चित समय के भीतर (हाल के बदलावों वाले डायलॉग में) वापस लाया जा सकता है। इस विकल्प को चुनने पर नोट तुरंत पूरी तरह मिटा दिए जाएंगे और उन्हें वापस लाना संभव नहीं होगा।",
|
||||
@@ -101,7 +102,9 @@
|
||||
"notes_to_be_deleted": "निम्नलिखित नोट डिलीट कर दिए जाएंगे ({{notesCount}})",
|
||||
"no_note_to_delete": "कोई भी नोट डिलीट नहीं होगा (केवल क्लोन हटाए जाएंगे)।",
|
||||
"broken_relations_to_be_deleted": "निम्नलिखित रिलेशन टूट जाएंगे और डिलीट हो जाएंगे ({{relationCount}})",
|
||||
"cancel": "रद्द करें"
|
||||
"cancel": "रद्द करें",
|
||||
"ok": "ठीक है",
|
||||
"deleted_relation_text": "नोट {{- note}} (जिसे डिलीट किया जाना है) का संदर्भ {{- source}} से शुरू होने वाले रिलेशन {{- relation}} में दिया गया है।"
|
||||
},
|
||||
"branch_prefix": {
|
||||
"edit_branch_prefix": "ब्रांच प्रीफ़िक्स एडिट करें",
|
||||
@@ -1046,6 +1049,7 @@
|
||||
"unprotecting-title": "अन-प्रोटेक्ट स्टेटस"
|
||||
},
|
||||
"relation_map": {
|
||||
"open_in_new_tab": "नए टैब में खोलें",
|
||||
"remove_note": "नोट हटाएं",
|
||||
"edit_title": "टाइटल एडिट करें",
|
||||
"rename_note": "नोट का नाम बदलें",
|
||||
@@ -1458,12 +1462,16 @@
|
||||
"description": "ये विकल्प सिर्फ़ डेस्कटॉप वर्जन के लिए हैं, ब्राउज़र अपना स्पेल चेक इस्तेमाल करेंगे।",
|
||||
"enable": "स्पेल चेक चालू करें",
|
||||
"language_code_label": "भाषा कोड (Language code)",
|
||||
"language_code_placeholder": "जैसे \"en-US\", \"hi-IN\"",
|
||||
"multiple_languages_info": "कई भाषाओं को कॉमा से अलग किया जा सकता है, जैसे \"en-US, hi-IN\"। ",
|
||||
"available_language_codes_label": "उपलब्ध भाषा कोड:",
|
||||
"restart-required": "स्पेल चेक में बदलाव ऐप रीस्टार्ट करने के बाद ही दिखेंगे।"
|
||||
},
|
||||
"sync_2": {
|
||||
"config_title": "सिंक कॉन्फ़िगरेशन",
|
||||
"server_address": "सर्वर एड्रेस (Address)",
|
||||
"timeout": "सिंक समय-सीमा (Timeout)",
|
||||
"timeout_unit": "मिलीसेकंड (milliseconds)",
|
||||
"proxy_label": "सिंक प्रॉक्सी सर्वर (वैकल्पिक)",
|
||||
"note": "नोट",
|
||||
"note_description": "अगर आप प्रॉक्सी खाली छोड़ते हैं, तो सिस्टम प्रॉक्सी का इस्तेमाल होगा।",
|
||||
|
||||
@@ -76,6 +76,7 @@
|
||||
"confirmation": "Konfirmasi"
|
||||
},
|
||||
"delete_notes": {
|
||||
"delete_notes_preview": "Hapus pratinjau catatan",
|
||||
"close": "Tutup",
|
||||
"delete_all_clones_description": "Hapus seluruh duplikat (bisa dikembalikan di menu revisi)",
|
||||
"erase_notes_description": "Penghapusan normal hanya menandai catatan sebagai dihapus dan dapat dipulihkan (melalui dialog versi revisi) dalam jangka waktu tertentu. Mencentang opsi ini akan menghapus catatan secara permanen seketika dan catatan tidak akan bisa dipulihkan kembali.",
|
||||
@@ -83,7 +84,9 @@
|
||||
"notes_to_be_deleted": "Catatan-catatan berikut akan dihapuskan ({{notesCount}})",
|
||||
"no_note_to_delete": "Tidak ada Catatan yang akan dihapus (hanya duplikat).",
|
||||
"broken_relations_to_be_deleted": "Hubungan berikut akan diputus dan dihapus ({{ relationCount}})",
|
||||
"cancel": "Batalkan"
|
||||
"cancel": "Batalkan",
|
||||
"ok": "Setuju",
|
||||
"deleted_relation_text": "Catatan {{- note}} (yang akan dihapus) dirujuk oleh relasi {{- relation}} yang berasal dari {{- source}}."
|
||||
},
|
||||
"clone_to": {
|
||||
"clone_notes_to": "Duplikat catatan ke…",
|
||||
|
||||
@@ -88,14 +88,17 @@
|
||||
"also_delete_note": "Rimuove anche la nota"
|
||||
},
|
||||
"delete_notes": {
|
||||
"ok": "OK",
|
||||
"close": "Chiudi",
|
||||
"delete_notes_preview": "Anteprima di eliminazione delle note",
|
||||
"delete_all_clones_description": "Elimina anche tutti i cloni (può essere ripristinato nella sezione cambiamenti recenti)",
|
||||
"erase_notes_description": "L'eliminazione normale (soft) marca le note come eliminate e potranno essere recuperate entro un certo lasso di tempo (dalla finestra dei cambiamenti recenti). Selezionando questa opzione le note si elimineranno immediatamente e non sarà possibile recuperarle.",
|
||||
"erase_notes_warning": "Elimina le note in modo permanente (non potrà essere disfatto), compresi tutti i cloni. Ciò forzerà un nuovo caricamento dell'applicazione.",
|
||||
"cancel": "Annulla",
|
||||
"notes_to_be_deleted": "Le seguenti note saranno eliminate ({{notesCount}})",
|
||||
"no_note_to_delete": "Nessuna nota sarà eliminata (solo i cloni).",
|
||||
"broken_relations_to_be_deleted": "Le seguenti relazioni saranno interrotte ed eliminate ({{relationCount}})"
|
||||
"broken_relations_to_be_deleted": "Le seguenti relazioni saranno interrotte ed eliminate ({{relationCount}})",
|
||||
"deleted_relation_text": "La nota {{- note}} (da eliminare) è referenziata dalla relazione {{- relation}} originata da {{- source}}."
|
||||
},
|
||||
"info": {
|
||||
"okButton": "OK",
|
||||
@@ -494,6 +497,7 @@
|
||||
"proxy_label": "Server Proxy per la sincronizzazione (opzionale)",
|
||||
"test_title": "Test di sincronizzazione",
|
||||
"timeout": "Timeout per la sincronizzazione",
|
||||
"timeout_unit": "millisecondi",
|
||||
"save": "Salva",
|
||||
"help": "Aiuto",
|
||||
"server_address": "Indirizzo dell'istanza del server",
|
||||
@@ -516,7 +520,7 @@
|
||||
"custom_name_label": "Nome del motore di ricerca personalizzato",
|
||||
"custom_name_placeholder": "Personalizza il nome del motore di ricerca",
|
||||
"custom_url_label": "L'URL del motore di ricerca personalizzato deve includere {keyword} come segnaposto per il termine di ricerca.",
|
||||
"custom_url_placeholder": "Personalizza indirizzo URL del motore di ricerca"
|
||||
"custom_url_placeholder": "Personalizza l'URL del motore di ricerca"
|
||||
},
|
||||
"sql_table_schemas": {
|
||||
"tables": "Tabelle"
|
||||
@@ -534,12 +538,12 @@
|
||||
"new_tab": "Nuova scheda"
|
||||
},
|
||||
"toc": {
|
||||
"table_of_contents": "Tabella dei Contenuti",
|
||||
"table_of_contents": "Sommario",
|
||||
"options": "Opzioni",
|
||||
"no_headings": "Nessun titolo."
|
||||
},
|
||||
"table_of_contents": {
|
||||
"title": "Tabella dei Contenuti",
|
||||
"title": "Sommario",
|
||||
"description": "L'indice apparirà nelle note di testo quando la nota contiene più di un numero definito di titoli. È possibile personalizzare questo numero:",
|
||||
"unit": "titoli",
|
||||
"disable_info": "È anche possibile utilizzare questa opzione per disattivare efficacemente l'indice impostando un numero molto alto.",
|
||||
@@ -589,7 +593,7 @@
|
||||
"collapseExpand": "collassa/espande il nodo",
|
||||
"notSet": "non impostato",
|
||||
"goBackForwards": "indietro/avanti nella cronologia",
|
||||
"showJumpToNoteDialog": "mostra <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/note-navigation.html#jump-to-note\">\"Vai a\"</a>",
|
||||
"showJumpToNoteDialog": "mostra <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/note-navigation.html#jump-to-note\">finestra \"Vai a\"</a>",
|
||||
"title": "Scheda riassuntiva",
|
||||
"noteNavigation": "Nota navigazione",
|
||||
"scrollToActiveNote": "scorri fino alla nota attiva",
|
||||
@@ -849,7 +853,7 @@
|
||||
"archived": "Le note con questa etichetta non saranno visibili per impostazione predefinita nei risultati di ricerca (anche nelle finestre di dialogo Vai a, Aggiungi collegamento ecc.).",
|
||||
"run_on_instance": "Definire su quale istanza di Trilium eseguire questa operazione. L'impostazione predefinita è tutte le istanze.",
|
||||
"exclude_from_export": "le note (con la loro sottostruttura) non saranno incluse in nessuna esportazione di note",
|
||||
"run": "definisce su quali eventi deve essere eseguito lo script. I valori possibili sono:\n<ul>\n<li>frontendStartup - quando il frontend Trilium viene avviato (o aggiornato), ma non su dispositivi mobili.</li>\n<li>mobileStartup - quando il frontend Trilium viene avviato (o aggiornato) su dispositivi mobili.</li>\n<li>backendStartup - quando viene avviato il backend Trilium.</li>\n<li>hourly - eseguire una volta all'ora. È possibile utilizzare l'etichetta aggiuntiva <code>runAtHour</code> per specificare a che ora.</li>\n<li>daily - eseguire una volta al giorno.</li>\n</ul>",
|
||||
"run": "definisce su quali eventi deve essere eseguito lo script. I valori possibili sono:\n<ul>\n<li>frontendStartup - quando il frontend Trilium viene avviato (o aggiornato), ma non su dispositivi mobili.</li>\n<li>mobileStartup - quando il frontend Trilium viene avviato (o aggiornato) su dispositivi mobili.</li>\n<li>backendStartup - quando viene avviato il backend Trilium</li>\n<li>hourly - eseguire una volta all'ora. È possibile utilizzare l'etichetta aggiuntiva <code>runAtHour</code> per specificare a che ora.</li>\n<li>daily - eseguire una volta al giorno</li>\n</ul>",
|
||||
"run_at_hour": "A che ora deve essere eseguito. Deve essere utilizzato insieme a <code>#run=hourly</code>. Può essere definito più volte per più esecuzioni durante il giorno.",
|
||||
"disable_inclusion": "gli script con questa etichetta non saranno inclusi nell'esecuzione dello script principale.",
|
||||
"sorted": "mantiene le note figlie ordinate alfabeticamente per titolo",
|
||||
@@ -913,8 +917,7 @@
|
||||
"print_landscape": "Quando si esporta in PDF, cambia l'orientamento della pagina da verticale a orizzontale.",
|
||||
"print_page_size": "Quando si esporta in PDF, modifica le dimensioni della pagina. Valori supportati: <code>A0</code>, <code>A1</code>, <code>A2</code>, <code>A3</code>, <code>A4</code>, <code>A5</code>, <code>A6</code>, <code>Legal</code>, <code>Letter</code>, <code>Tabloid</code>, <code>Ledger</code>.",
|
||||
"color_type": "Colore",
|
||||
"share_root": "segna la nota che viene servita su /share root.",
|
||||
"textarea": "Testo su più righe"
|
||||
"share_root": "segna la nota che viene servita su /share root."
|
||||
},
|
||||
"attribute_editor": {
|
||||
"help_text_body1": "Per aggiungere un'etichetta, basta digitare ad esempio <code>#rock</code> oppure, se si desidera aggiungere anche un valore, ad esempio <code>#year = 2020</code>",
|
||||
@@ -1096,7 +1099,7 @@
|
||||
"show_help": "Mostra aiuto",
|
||||
"about": "Informazioni su Trilium Notes",
|
||||
"logout": "Esci",
|
||||
"show-cheatsheet": "Mostra la scheda riassuntiva",
|
||||
"show-cheatsheet": "Mostra il foglietto illustrativo",
|
||||
"toggle-zen-mode": "Modalità Zen",
|
||||
"new-version-available": "Nuovo aggiornamento disponibile",
|
||||
"download-update": "Ottieni la versione {{latestVersion}}",
|
||||
@@ -1145,8 +1148,7 @@
|
||||
"export_as_image": "Esporta come immagine",
|
||||
"export_as_image_png": "PNG (raster)",
|
||||
"export_as_image_svg": "SVG (vector)",
|
||||
"note_map": "Mappa",
|
||||
"view_ocr_text": "Visualizza il testo OCR"
|
||||
"note_map": "Mappa"
|
||||
},
|
||||
"onclick_button": {
|
||||
"no_click_handler": "Il widget pulsante '{{componentId}}' non ha un gestore di clic definito"
|
||||
@@ -1422,6 +1424,7 @@
|
||||
"unprotecting-title": "Stato non protetto"
|
||||
},
|
||||
"relation_map": {
|
||||
"open_in_new_tab": "Apri in una nuova scheda",
|
||||
"remove_note": "Rimuovi nota",
|
||||
"edit_title": "Modifica titolo",
|
||||
"rename_note": "Rinomina nota",
|
||||
@@ -1436,8 +1439,7 @@
|
||||
"note_already_in_diagram": "Nota che \"{{title}}\" è già presente nel diagramma.",
|
||||
"enter_title_of_new_note": "Inserisci il titolo della nuova nota",
|
||||
"default_new_note_title": "nuova nota",
|
||||
"click_on_canvas_to_place_new_note": "Clicca sulla tela per inserire una nuova nota",
|
||||
"rename_relation": "Rinomina relazione"
|
||||
"click_on_canvas_to_place_new_note": "Clicca sulla tela per inserire una nuova nota"
|
||||
},
|
||||
"vacuum_database": {
|
||||
"title": "Pulizia del database",
|
||||
@@ -1539,28 +1541,12 @@
|
||||
},
|
||||
"images": {
|
||||
"images_section_title": "Immagini",
|
||||
"download_images_automatically": "Scarica automaticamente le immagini",
|
||||
"download_images_description": "Scarica le immagini online a cui si fa riferimento nel codice HTML incollato, in modo che siano disponibili offline.",
|
||||
"enable_image_compression": "Compressione delle immagini",
|
||||
"max_image_dimensions": "Dimensioni massime dell'immagine",
|
||||
"download_images_automatically": "Scarica automaticamente le immagini per l'utilizzo offline.",
|
||||
"download_images_description": "L'HTML incollato può contenere riferimenti a immagini online; Trilium troverà tali riferimenti e scaricherà le immagini in modo che siano disponibili offline.",
|
||||
"enable_image_compression": "Abilita la compressione delle immagini",
|
||||
"max_image_dimensions": "Larghezza/altezza massima di un'immagine (l'immagine verrà ridimensionata se supera questa impostazione).",
|
||||
"max_image_dimensions_unit": "pixel",
|
||||
"jpeg_quality_description": "Il range consigliato è compreso tra 50 e 85. Valori più bassi riducono le dimensioni del file, mentre valori più alti preservano i dettagli.",
|
||||
"enable_image_compression_description": "Comprimi e ridimensiona le immagini al momento del caricamento o dell'inserimento.",
|
||||
"max_image_dimensions_description": "Le immagini che superano queste dimensioni verranno ridimensionate automaticamente.",
|
||||
"jpeg_quality": "Qualità JPEG",
|
||||
"ocr_section_title": "Estrazione di testo (OCR)",
|
||||
"ocr_related_content_languages": "Lingue dei contenuti (utilizzate per l'estrazione del testo)",
|
||||
"ocr_auto_process": "Elaborazione automatica dei nuovi file",
|
||||
"ocr_auto_process_description": "Estrai automaticamente il testo dai file appena caricati o incollati.",
|
||||
"ocr_min_confidence": "Livello minimo di confidenza",
|
||||
"ocr_confidence_description": "Estrai solo il testo che supera questa soglia di affidabilità. Valori inferiori includono più testo, ma potrebbero risultare meno accurati.",
|
||||
"batch_ocr_title": "Elabora i file esistenti",
|
||||
"batch_ocr_description": "Estrai il testo da tutte le immagini, i PDF e i documenti Office presenti nei tuoi appunti. L'operazione potrebbe richiedere un po' di tempo a seconda del numero di file.",
|
||||
"batch_ocr_start": "Avvia l'elaborazione in batch",
|
||||
"batch_ocr_starting": "Avvio dell'elaborazione in batch...",
|
||||
"batch_ocr_progress": "Elaborazione di {{processed}} su {{total}} file...",
|
||||
"batch_ocr_completed": "Elaborazione in batch completata! Sono stati elaborati {{processed}} file.",
|
||||
"batch_ocr_error": "Errore durante l'elaborazione in batch: {{error}}"
|
||||
"jpeg_quality_description": "Qualità JPEG (10 - qualità peggiore, 100 - qualità migliore, 50 - 85 è consigliato)"
|
||||
},
|
||||
"attachment_erasure_timeout": {
|
||||
"attachment_erasure_timeout": "Timeout cancellazione allegato",
|
||||
@@ -1668,15 +1654,12 @@
|
||||
"spellcheck": {
|
||||
"title": "Controllo ortografico",
|
||||
"description": "Queste opzioni sono valide solo per le versioni desktop; i browser utilizzeranno il proprio controllo ortografico nativo.",
|
||||
"enable": "Controlla l'ortografia",
|
||||
"language_code_label": "Lingue del controllo ortografico",
|
||||
"restart-required": "Le modifiche alle opzioni di controllo ortografico avranno effetto dopo il riavvio dell'applicazione.",
|
||||
"custom_dictionary_title": "Dizionario personalizzato",
|
||||
"custom_dictionary_description": "Le parole aggiunte al dizionario vengono sincronizzate su tutti i tuoi dispositivi.",
|
||||
"custom_dictionary_edit": "Parole personalizzate",
|
||||
"custom_dictionary_edit_description": "Modifica l'elenco delle parole che non devono essere segnalate dal correttore ortografico. Le modifiche saranno visibili dopo il riavvio.",
|
||||
"custom_dictionary_open": "Modifica il dizionario",
|
||||
"related_description": "Configura le lingue del controllo ortografico e il dizionario personalizzato."
|
||||
"enable": "Abilita il controllo ortografico",
|
||||
"language_code_label": "Codice/i della lingua",
|
||||
"language_code_placeholder": "ad esempio \"en-US\", \"de-AT\"",
|
||||
"multiple_languages_info": "È possibile separare più lingue con una virgola, ad esempio \"en-US, de-DE, cs\". ",
|
||||
"available_language_codes_label": "Codici lingua disponibili:",
|
||||
"restart-required": "Le modifiche alle opzioni di controllo ortografico avranno effetto dopo il riavvio dell'applicazione."
|
||||
},
|
||||
"api_log": {
|
||||
"close": "Vicino"
|
||||
@@ -1735,8 +1718,7 @@
|
||||
"new-feature": "Nuovo",
|
||||
"collections": "Collezioni",
|
||||
"ai-chat": "Chat con IA",
|
||||
"spreadsheet": "Foglio di calcolo",
|
||||
"llm-chat": "Chat con IA"
|
||||
"spreadsheet": "Foglio di calcolo"
|
||||
},
|
||||
"protect_note": {
|
||||
"toggle-on": "Proteggi la nota",
|
||||
@@ -1957,7 +1939,7 @@
|
||||
},
|
||||
"content_language": {
|
||||
"title": "Lingue dei contenuti",
|
||||
"description": "Seleziona una o più lingue che devono comparire nell'elenco di selezione delle lingue nella sezione \"Proprietà di base\" di una nota di testo in sola lettura o modificabile. Ciò consentirà di utilizzare funzioni quali il controllo ortografico, il supporto per la scrittura da destra a sinistra e l'estrazione del testo (OCR)."
|
||||
"description": "Seleziona una o più lingue che desideri visualizzare nella sezione \"Proprietà di base\" di una nota di testo di sola lettura o modificabile. Ciò consentirà funzionalità come il controllo ortografico o il supporto per la scrittura da destra a sinistra."
|
||||
},
|
||||
"switch_layout_button": {
|
||||
"title_vertical": "Sposta il riquadro di modifica in basso",
|
||||
@@ -2069,9 +2051,7 @@
|
||||
"title": "Opzioni sperimentali",
|
||||
"disclaimer": "Queste opzioni sono sperimentali e potrebbero causare instabilità. Usare con cautela.",
|
||||
"new_layout_name": "Nuovo layout",
|
||||
"new_layout_description": "Prova il nuovo layout per un look più moderno e una maggiore usabilità. Soggetto a modifiche significative nelle prossime versioni.",
|
||||
"llm_name": "Chat con IA / LLM",
|
||||
"llm_description": "Attiva la barra laterale della chat con IA e le note della chat LLM basate su modelli linguistici di grandi dimensioni."
|
||||
"new_layout_description": "Prova il nuovo layout per un look più moderno e una maggiore usabilità. Soggetto a modifiche significative nelle prossime versioni."
|
||||
},
|
||||
"server": {
|
||||
"unknown_http_error_title": "Errore di comunicazione con il server",
|
||||
@@ -2218,167 +2198,5 @@
|
||||
},
|
||||
"setup_form": {
|
||||
"more_info": "Per saperne di più"
|
||||
},
|
||||
"media": {
|
||||
"play": "Gioca (Barra spaziatrice)",
|
||||
"pause": "Pausa (Barra spaziatrice)",
|
||||
"back-10s": "Indietro di 10 (tasto freccia sinistra)",
|
||||
"forward-30s": "Avanti 30s",
|
||||
"mute": "Muto (M)",
|
||||
"unmute": "Riattiva audio (M)",
|
||||
"playback-speed": "Velocità di riproduzione",
|
||||
"loop": "Ciclo",
|
||||
"disable-loop": "Disattiva il ciclo",
|
||||
"rotate": "Ruota",
|
||||
"picture-in-picture": "Immagine nell'immagine",
|
||||
"exit-picture-in-picture": "Esci dalla modalità picture-in-picture",
|
||||
"fullscreen": "Schermo intero (F)",
|
||||
"exit-fullscreen": "Esci dalla modalità a schermo intero",
|
||||
"unsupported-format": "Per questo formato di file non è disponibile l'anteprima multimediale:\n{{mime}}",
|
||||
"zoom-to-fit": "Ingrandisci per riempire",
|
||||
"zoom-reset": "Ripristina lo zoom a schermo intero"
|
||||
},
|
||||
"mermaid": {
|
||||
"placeholder": "Digita il contenuto del tuo diagramma Mermaid oppure utilizza uno dei diagrammi di esempio riportati di seguito.",
|
||||
"sample_diagrams": "Esempi di diagrammi:",
|
||||
"sample_flowchart": "Diagramma di flusso",
|
||||
"sample_class": "Classe",
|
||||
"sample_sequence": "Sequenza",
|
||||
"sample_entity_relationship": "Relazioni tra entità",
|
||||
"sample_state": "Stato",
|
||||
"sample_mindmap": "Mappa mentale",
|
||||
"sample_architecture": "Architettura",
|
||||
"sample_block": "Blocco",
|
||||
"sample_c4": "C4",
|
||||
"sample_gantt": "Gantt",
|
||||
"sample_git": "Git",
|
||||
"sample_kanban": "Kanban",
|
||||
"sample_packet": "Packet",
|
||||
"sample_pie": "Torta",
|
||||
"sample_quadrant": "Quadrante",
|
||||
"sample_radar": "Radar",
|
||||
"sample_requirement": "Requisito",
|
||||
"sample_sankey": "Chiave",
|
||||
"sample_timeline": "Cronologia",
|
||||
"sample_treemap": "Treemap",
|
||||
"sample_user_journey": "Percorso dell'utente",
|
||||
"sample_xy": "XY",
|
||||
"sample_venn": "Venn",
|
||||
"sample_ishikawa": "Ishikawa",
|
||||
"sample_treeview": "TreeView",
|
||||
"sample_wardley": "Mappa di Wardley"
|
||||
},
|
||||
"llm_chat": {
|
||||
"placeholder": "Scrivi un messaggio...",
|
||||
"send": "Invia",
|
||||
"sending": "Invio in corso...",
|
||||
"empty_state": "Inizia una conversazione scrivendo un messaggio qui sotto.",
|
||||
"searching_web": "Ricerca sul web...",
|
||||
"web_search": "Ricerca sul web",
|
||||
"note_tools": "Nota di accesso",
|
||||
"sources": "Fonti",
|
||||
"extended_thinking": "Riflessioni approfondite",
|
||||
"legacy_models": "Modelli precedenti",
|
||||
"thinking": "Sto riflettendo...",
|
||||
"thought_process": "Processo mentale",
|
||||
"tool_calls": "{{count}} chiamata/e di funzione",
|
||||
"input": "Dati in ingresso",
|
||||
"result": "Risultato",
|
||||
"error": "Errore",
|
||||
"tool_error": "fallito",
|
||||
"total_tokens": "{{total}} gettoni",
|
||||
"tokens_detail": "{{prompt}} prompt + {{completion}} completamento",
|
||||
"tokens_used": "{{prompt}} prompt + {{completion}} completamento = {{total}} token",
|
||||
"tokens_used_with_cost": "{{prompt}} prompt + {{completion}} completamento = {{total}} token (~${{cost}})",
|
||||
"tokens_used_with_model": "{{model}}: {{prompt}} prompt + {{completion}} completamento = {{total}} token",
|
||||
"tokens_used_with_model_and_cost": "{{model}}: {{prompt}} prompt + {{completion}} completamento = {{total}} token (~${{cost}})",
|
||||
"tokens": "tokens",
|
||||
"context_used": "{{percentage}}% utilizzato",
|
||||
"note_context_enabled": "Clicca qui per disattivare il contesto della nota: {{title}}",
|
||||
"note_context_disabled": "Clicca per includere la nota corrente nel contesto",
|
||||
"no_provider_message": "Non è stato configurato alcun fornitore di IA. Aggiungine uno per iniziare a chattare.",
|
||||
"add_provider": "Aggiungi un fornitore di IA",
|
||||
"sources_summary": "{{count}} fonti provenienti da {{sites}} siti"
|
||||
},
|
||||
"sidebar_chat": {
|
||||
"title": "Chat AI",
|
||||
"launcher_title": "Apri Chat AI",
|
||||
"new_chat": "Inizia una nuova chat",
|
||||
"save_chat": "Salva la chat negli appunti",
|
||||
"empty_state": "Avvia una conversazione",
|
||||
"history": "Cronologia delle chat",
|
||||
"recent_chats": "Conversazioni recenti",
|
||||
"no_chats": "Nessuna conversazione precedente"
|
||||
},
|
||||
"llm": {
|
||||
"settings_title": "AI / LLM",
|
||||
"settings_description": "Configurare le integrazioni con l'intelligenza artificiale e i modelli linguistici di grandi dimensioni.",
|
||||
"add_provider": "Aggiungi fornitore",
|
||||
"add_provider_title": "Aggiungi un fornitore di IA",
|
||||
"configured_providers": "Fornitori configurati",
|
||||
"no_providers_configured": "Non sono stati ancora configurati fornitori.",
|
||||
"provider_name": "Nome",
|
||||
"provider_type": "Fornitore",
|
||||
"actions": "Azioni",
|
||||
"delete_provider": "Elimina",
|
||||
"delete_provider_confirmation": "Sei sicuro di voler eliminare il provider \"{{name}}\"?",
|
||||
"api_key": "Chiave API",
|
||||
"api_key_placeholder": "Inserisci la tua chiave API",
|
||||
"cancel": "Annulla",
|
||||
"feature_not_enabled": "Abilita la funzione sperimentale LLM in Impostazioni → Avanzate → Funzioni sperimentali per utilizzare le integrazioni basate sull'intelligenza artificiale.",
|
||||
"mcp_title": "MCP (Model Context Protocol)",
|
||||
"mcp_enabled": "Server MCP",
|
||||
"mcp_enabled_description": "Rendi pubblico un endpoint MCP (Model Context Protocol) in modo che gli assistenti di programmazione basati sull'intelligenza artificiale (ad esempio Claude Code, GitHub Copilot) possano leggere e modificare le tue note. L'endpoint è accessibile solo da localhost.",
|
||||
"mcp_endpoint_title": "URL dell'endpoint",
|
||||
"mcp_endpoint_description": "Aggiungi questo URL alla configurazione MCP del tuo assistente AI",
|
||||
"tools": {
|
||||
"search_notes": "Cerca nelle note",
|
||||
"get_note": "Prendi nota",
|
||||
"get_note_content": "Visualizza il contenuto della nota",
|
||||
"update_note_content": "Aggiorna il contenuto della nota",
|
||||
"append_to_note": "Aggiungi alla nota",
|
||||
"create_note": "Crea nota",
|
||||
"get_attributes": "Recupera gli attributi",
|
||||
"get_attribute": "Ottieni attributo",
|
||||
"set_attribute": "Imposta attributo",
|
||||
"delete_attribute": "Elimina attributo",
|
||||
"get_child_notes": "Recupera le note relative ai figli",
|
||||
"get_subtree": "Ottieni sottostruttura",
|
||||
"load_skill": "Carica skill",
|
||||
"web_search": "Ricerca sul web",
|
||||
"note_in_parent": "<Note/> in <Parent/>",
|
||||
"get_attachment": "Scarica l'allegato",
|
||||
"get_attachment_content": "Leggi il contenuto dell'allegato"
|
||||
}
|
||||
},
|
||||
"ocr": {
|
||||
"extracted_text": "Testo estratto (OCR)",
|
||||
"extracted_text_title": "Testo estratto (OCR)",
|
||||
"loading_text": "Caricamento del testo OCR in corso...",
|
||||
"no_text_available": "Non è disponibile alcun testo OCR",
|
||||
"no_text_explanation": "Questo documento non è stato sottoposto a elaborazione OCR per l'estrazione del testo oppure non è stato trovato alcun testo.",
|
||||
"failed_to_load": "Impossibile caricare il testo OCR",
|
||||
"process_now": "Elaborazione OCR",
|
||||
"processing": "Elaborazione in corso...",
|
||||
"processing_started": "L'elaborazione OCR è stata avviata. Attendere qualche istante e aggiorna.",
|
||||
"processing_complete": "Elaborazione OCR completata.",
|
||||
"processing_failed": "Impossibile avviare l'elaborazione OCR",
|
||||
"text_filtered_low_confidence": "L'OCR ha rilevato il testo con un livello di affidabilità del {{confidence}}%, ma è stato scartato perché la soglia minima impostata è del {{threshold}}%.",
|
||||
"open_media_settings": "Apri Impostazioni",
|
||||
"view_extracted_text": "Visualizza il testo estratto (OCR)"
|
||||
},
|
||||
"mind-map": {
|
||||
"addChild": "Aggiungi figlio",
|
||||
"addParent": "Aggiungi genitore",
|
||||
"addSibling": "Aggiungi un fratello o una sorella",
|
||||
"removeNode": "Rimuovi nodo",
|
||||
"focus": "Modalità Focus",
|
||||
"cancelFocus": "Annulla modalità Focus",
|
||||
"moveUp": "Sposta su",
|
||||
"moveDown": "Sposta giù",
|
||||
"link": "Collegamento",
|
||||
"linkBidirectional": "Collegamento bidirezionale",
|
||||
"clickTips": "Clicca sul nodo di destinazione",
|
||||
"summary": "Sommario"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,8 +111,11 @@
|
||||
"notes_to_be_deleted": "以下のノートが削除されます ({{notesCount}})",
|
||||
"no_note_to_delete": "ノートは削除されません(クローンのみ)。",
|
||||
"cancel": "キャンセル",
|
||||
"ok": "OK",
|
||||
"close": "閉じる",
|
||||
"broken_relations_to_be_deleted": "次のリレーション ({{relationCount}})は壊れているので消去されます"
|
||||
"delete_notes_preview": "ノートのプレビューを削除",
|
||||
"broken_relations_to_be_deleted": "次のリレーション ({{relationCount}})は壊れているので消去されます",
|
||||
"deleted_relation_text": "削除予定のノート{{- note}}は{{- source}}からリレーション{{- relation}}によって参照されています."
|
||||
},
|
||||
"calendar": {
|
||||
"mon": "月",
|
||||
@@ -483,8 +486,7 @@
|
||||
"advanced": "高度",
|
||||
"export_as_image": "画像としてエクスポート",
|
||||
"export_as_image_png": "PNG (raster)",
|
||||
"export_as_image_svg": "SVG (vector)",
|
||||
"view_ocr_text": "OCR テキストを表示"
|
||||
"export_as_image_svg": "SVG (vector)"
|
||||
},
|
||||
"command_palette": {
|
||||
"export_note_title": "ノートをエクスポート",
|
||||
@@ -573,10 +575,7 @@
|
||||
"expand_first_level": "直下の子を展開",
|
||||
"expand_nth_level": "{{depth}} 階層下まで展開",
|
||||
"expand_all_levels": "すべての階層を展開",
|
||||
"hide_child_notes": "ツリー内の子ノートを非表示",
|
||||
"open_all_in_tabs": "すべて開く",
|
||||
"open_all_in_tabs_tooltip": "すべての結果を新しいタブで開く",
|
||||
"open_all_confirm": "{{count}} 件のノートが新しいタブで開かれます。続行しますか?"
|
||||
"hide_child_notes": "ツリー内の子ノートを非表示"
|
||||
},
|
||||
"note_types": {
|
||||
"geo-map": "ジオマップ",
|
||||
@@ -589,7 +588,7 @@
|
||||
"note-map": "ノートマップ",
|
||||
"render-note": "レンダリングノート",
|
||||
"book": "コレクション",
|
||||
"mermaid-diagram": "マーメイド図",
|
||||
"mermaid-diagram": "Mermaidダイアグラム",
|
||||
"canvas": "キャンバス",
|
||||
"web-view": "Web ビュー",
|
||||
"mind-map": "マインドマップ",
|
||||
@@ -602,8 +601,7 @@
|
||||
"new-feature": "New",
|
||||
"collections": "コレクション",
|
||||
"ai-chat": "AI チャット",
|
||||
"spreadsheet": "スプレッドシート",
|
||||
"llm-chat": "AI チャット"
|
||||
"spreadsheet": "スプレッドシート"
|
||||
},
|
||||
"edited_notes": {
|
||||
"no_edited_notes_found": "この日の編集されたノートはまだありません...",
|
||||
@@ -899,28 +897,12 @@
|
||||
},
|
||||
"images": {
|
||||
"images_section_title": "画像",
|
||||
"download_images_automatically": "画像を自動的にダウンロードする。",
|
||||
"download_images_description": "貼り付けた HTML 内の参照画像をダウンロードし、オフラインでも利用できるようにする。",
|
||||
"enable_image_compression": "画像の圧縮",
|
||||
"max_image_dimensions": "画像の最大サイズ",
|
||||
"download_images_automatically": "画像を自動的にダウンロードしてオフラインで使用可能にする。",
|
||||
"download_images_description": "貼り付けられたHTMLにはオンライン画像への参照が含まれていることがありますが、Triliumはそれらの参照を見つけて画像をダウンロードし、オフラインで利用できるようにします。",
|
||||
"enable_image_compression": "画像の圧縮を有効にする",
|
||||
"max_image_dimensions": "画像の最大幅/高さ(この設定を超えると画像はリサイズされます)。",
|
||||
"max_image_dimensions_unit": "ピクセル",
|
||||
"jpeg_quality_description": "推奨範囲は50~85です。値が低いほどファイルサイズが小さくなり、値が高いほどディテールが保持されます。",
|
||||
"enable_image_compression_description": "画像をアップロードまたは貼り付ける際に、画像を圧縮およびサイズ変更します。",
|
||||
"max_image_dimensions_description": "このサイズを超える画像は自動的にサイズ変更されます",
|
||||
"jpeg_quality": "JPEG 画質",
|
||||
"ocr_section_title": "テキスト抽出(OCR)",
|
||||
"ocr_related_content_languages": "コンテンツ言語(テキスト抽出に使用)",
|
||||
"ocr_auto_process": "新しいファイルを自動処理",
|
||||
"ocr_auto_process_description": "新しくアップロードまたは貼り付けられたファイルからテキストを自動的に抽出します。",
|
||||
"ocr_min_confidence": "最低限の信頼度",
|
||||
"ocr_confidence_description": "この信頼度閾値以上のテキストのみを抽出します。信頼度が低いほど抽出されるテキストの量は増えますが、精度が低下する可能性があります。",
|
||||
"batch_ocr_title": "既存ファイルの処理",
|
||||
"batch_ocr_description": "ノート内の既存の画像、PDF、Office 文書からテキストを抽出します。ファイル数によっては時間がかかる場合があります。",
|
||||
"batch_ocr_start": "バッチ処理を開始します",
|
||||
"batch_ocr_starting": "バッチ処理を開始しています...",
|
||||
"batch_ocr_progress": "{{total}} ファイルのうち {{processed}} ファイルを処理中...",
|
||||
"batch_ocr_completed": "バッチ処理が完了しました!{{processed}} ファイルを処理しました。",
|
||||
"batch_ocr_error": "バッチ処理中にエラーが発生しました: {{error}}"
|
||||
"jpeg_quality_description": "JPEGの品質(10 - 最低品質、100 - 最高品質、50 - 80を推奨)"
|
||||
},
|
||||
"search_engine": {
|
||||
"title": "検索エンジン",
|
||||
@@ -933,7 +915,7 @@
|
||||
"custom_name_label": "カスタム検索エンジンの名前",
|
||||
"custom_name_placeholder": "カスタム検索エンジンの名前",
|
||||
"custom_url_label": "カスタム検索エンジンのURLには、検索語句のプレースホルダーとして {keyword} を含める必要があります。",
|
||||
"custom_url_placeholder": "検索エンジンの URL をカスタマイズ",
|
||||
"custom_url_placeholder": "カスタム検索エンジンのurl",
|
||||
"save_button": "保存"
|
||||
},
|
||||
"tray": {
|
||||
@@ -1001,8 +983,7 @@
|
||||
"date-and-time": "日時",
|
||||
"path": "パス",
|
||||
"database_backed_up_to": "データベースは{{backupFilePath}}にバックアップされました",
|
||||
"no_backup_yet": "バックアップがありません",
|
||||
"download": "ダウンロード"
|
||||
"no_backup_yet": "バックアップがありません"
|
||||
},
|
||||
"password": {
|
||||
"wiki": "wiki",
|
||||
@@ -1028,20 +1009,18 @@
|
||||
"spellcheck": {
|
||||
"title": "スペルチェック",
|
||||
"description": "これらのオプションはデスクトップビルドにのみ適用され、ブラウザはそれぞれのネイティブスペルチェックを使用します。",
|
||||
"enable": "スペルチェック",
|
||||
"language_code_label": "スペルチェック対応言語",
|
||||
"restart-required": "スペルチェックオプションの変更は、アプリケーションの再起動後に有効になります。",
|
||||
"custom_dictionary_title": "カスタム辞書",
|
||||
"custom_dictionary_description": "辞書に追加した単語は、すべてのデバイス間で同期されます。",
|
||||
"custom_dictionary_edit": "カスタム単語",
|
||||
"custom_dictionary_edit_description": "スペルチェッカーでエラーとして検出されないようにする単語リストを編集します。変更は再起動後に反映されます。",
|
||||
"custom_dictionary_open": "辞書の編集",
|
||||
"related_description": "スペルチェック対応言語とカスタム辞書を設定します。"
|
||||
"enable": "スペルチェックを有効",
|
||||
"language_code_label": "言語コード",
|
||||
"language_code_placeholder": "例えば \"en-US\", \"de-AT\"",
|
||||
"multiple_languages_info": "複数の言語はカンマで区切ることができます。例: \"en-US, de-DE, cs\"。 ",
|
||||
"available_language_codes_label": "使用可能な言語コード:",
|
||||
"restart-required": "スペルチェックオプションの変更は、アプリケーションの再起動後に有効になります。"
|
||||
},
|
||||
"sync_2": {
|
||||
"config_title": "同期設定",
|
||||
"server_address": "サーバーインスタンスのアドレス",
|
||||
"timeout": "同期タイムアウト",
|
||||
"timeout_unit": "ミリ秒",
|
||||
"proxy_label": "同期プロキシサーバー(任意)",
|
||||
"note": "注",
|
||||
"note_description": "プロキシ設定を空白のままにすると、システムプロキシが使用されます(デスクトップ/electronビルドにのみ適用されます)。",
|
||||
@@ -1051,8 +1030,7 @@
|
||||
"test_title": "同期のテスト",
|
||||
"test_description": "これは同期サーバとの接続とハンドシェイクをテストします。同期サーバーが初期化されていない場合、ローカルドキュメントと同期するように設定します。",
|
||||
"test_button": "同期試行",
|
||||
"handshake_failed": "同期サーバーのハンドシェイクに失敗しました。エラー: {{message}}",
|
||||
"timeout_description": "同期接続が遅い場合に、接続を諦めるまでの待機時間。ネットワークが不安定な場合は、この時間を長く設定してください。"
|
||||
"handshake_failed": "同期サーバーのハンドシェイクに失敗しました。エラー: {{message}}"
|
||||
},
|
||||
"api_log": {
|
||||
"close": "閉じる"
|
||||
@@ -1124,7 +1102,7 @@
|
||||
"calendar_root": "dayノートのルートとして使用するノートをマークします。このようにマークできるのは 1 つだけです。",
|
||||
"archived": "このラベルの付いたノートは、デフォルトでは検索結果に表示されません (ジャンプ先、リンクの追加ダイアログなどにも表示されません)。",
|
||||
"exclude_from_export": "ノート(サブツリーを含む)はノートのエクスポートには含まれません",
|
||||
"run": "スクリプトを実行するイベントを定義します。指定可能な値は以下の通りです:\n<ul>\n<li>frontendStartup - Trilium フロントエンドの起動時(または更新時)に実行されます。モバイルでは実行されません。</li>\n<li>mobileStartup - モバイルでの Trilium フロントエンドの起動時(または更新時)に実行されます。</li>\n<li>backendStartup - Trilium バックエンドの起動時。</li>\n<li>hourly - 1時間ごとに実行。 <code>runAtHour</code> というラベルを追加することで、実行時刻を指定できます。</li>\n<li>daily - 1日に1回実行。</li>\n</ul>",
|
||||
"run": "どのイベントでスクリプトを実行するかを定義します。可能な値は次の通り:\n<ul>\n<li>frontendStartup - Trilium フロントエンドが起動(または更新)されたとき。モバイルは除く</li>\n<li>mobileStartup - モバイルで Trilium フロントエンドが起動(または更新)されたとき。</li>\n<li>backendStartup - Trilium バックエンドが起動したとき</li>\n<li>hourly - 1時間に1回実行します。 <code>runAtHour</code> というラベルを追加して、実行時刻を指定できます。</li>\n<li>daily - 1日に1回実行</li>\n</ul>",
|
||||
"run_on_instance": "どの Trilium インスタンスでこれを実行するかを定義します。デフォルトはすべてのインスタンスです。",
|
||||
"run_at_hour": "何時に実行するかを指定します。 <code>#run=hourly</code> と併用してください。1日に複数回実行したい場合は、複数回定義できます。",
|
||||
"disable_inclusion": "このラベルが付いたスクリプトは親スクリプトの実行には含まれません。",
|
||||
@@ -1202,8 +1180,7 @@
|
||||
"is_owned_by_note": "ノートによって所有されています",
|
||||
"and_more": "...その他 {{count}} 件。",
|
||||
"print_landscape": "PDF にエクスポートするときに、ページの向きを縦向きではなく横向きに変更します。",
|
||||
"print_page_size": "PDF にエクスポートするときに、ページのサイズを変更します。サポートされる値: <code>A0</code>, <code>A1</code>, <code>A2</code>, <code>A3</code>, <code>A4</code>, <code>A5</code>, <code>A6</code>, <code>Legal</code>, <code>Letter</code>, <code>Tabloid</code>, <code>Ledger</code>。",
|
||||
"textarea": "複数行テキスト"
|
||||
"print_page_size": "PDF にエクスポートするときに、ページのサイズを変更します。サポートされる値: <code>A0</code>, <code>A1</code>, <code>A2</code>, <code>A3</code>, <code>A4</code>, <code>A5</code>, <code>A6</code>, <code>Legal</code>, <code>Letter</code>, <code>Tabloid</code>, <code>Ledger</code>。"
|
||||
},
|
||||
"link_context_menu": {
|
||||
"open_note_in_popup": "クイック編集",
|
||||
@@ -1412,7 +1389,7 @@
|
||||
},
|
||||
"content_language": {
|
||||
"title": "コンテンツの言語",
|
||||
"description": "読み取り専用または編集可能なテキストノートの基本プロパティセクションの言語選択に表示する言語を 1 つ以上選択してください。これにより、スペルチェック、右から左へのサポート、テキスト抽出(OCR)などの機能が利用できるようになります。"
|
||||
"description": "読み取り専用または編集可能なテキストノートの基本プロパティセクションの言語選択に表示する言語を 1 つ以上選択します。これにより、スペルチェックや右から左へのサポートなどの機能が利用できるようになります。"
|
||||
},
|
||||
"png_export_button": {
|
||||
"button_title": "図をPNG形式でエクスポート"
|
||||
@@ -1543,8 +1520,7 @@
|
||||
"collapse": "通常サイズに折りたたむ",
|
||||
"title": "ノートマップ",
|
||||
"link-distance": "リンク距離",
|
||||
"fix-nodes": "ノードを修正",
|
||||
"too-many-notes": "このサブツリーには {{count}} 件のノートが含まれており、ノートマップに表示できる {{max}} の上限を超えています。"
|
||||
"fix-nodes": "ノードを修正"
|
||||
},
|
||||
"owned_attribute_list": {
|
||||
"owned_attributes": "所有属性"
|
||||
@@ -1561,6 +1537,7 @@
|
||||
"url_placeholder": "http://web サイト..."
|
||||
},
|
||||
"relation_map": {
|
||||
"open_in_new_tab": "新しいタブで開く",
|
||||
"remove_note": "ノートを削除",
|
||||
"edit_title": "タイトルを編集",
|
||||
"rename_note": "ノート名を変更",
|
||||
@@ -1575,8 +1552,7 @@
|
||||
"click_on_canvas_to_place_new_note": "キャンバスをクリックして新しいノートを配置",
|
||||
"connection_exists": "これらのノート間の接続 '{{name}}' は既に存在します。",
|
||||
"start_dragging_relations": "ここからリレーションをドラッグして、別のノートにドロップします。",
|
||||
"note_already_in_diagram": "ノート「{{title}}」はすでに図に含まれています。",
|
||||
"rename_relation": "リレーション名の変更"
|
||||
"note_already_in_diagram": "ノート「{{title}}」はすでに図に含まれています。"
|
||||
},
|
||||
"database_anonymization": {
|
||||
"title": "データベースの匿名化",
|
||||
@@ -2074,9 +2050,7 @@
|
||||
"title": "実験オプション",
|
||||
"disclaimer": "これらのオプションは試験的なもので、動作が不安定になる可能性があります。注意してご使用ください。",
|
||||
"new_layout_name": "新しいレイアウト",
|
||||
"new_layout_description": "よりモダンな外観と使いやすさが向上した新しいレイアウトをお試しください。今後のリリースで大幅な変更が加えられる可能性があります。",
|
||||
"llm_name": "AI / LLM チャット",
|
||||
"llm_description": "大規模言語モデルを活用した AI チャットサイドバーと LLM チャットノートを有効にします。"
|
||||
"new_layout_description": "よりモダンな外観と使いやすさが向上した新しいレイアウトをお試しください。今後のリリースで大幅な変更が加えられる可能性があります。"
|
||||
},
|
||||
"breadcrumb_badges": {
|
||||
"read_only_explicit": "読み取り専用",
|
||||
@@ -2194,167 +2168,5 @@
|
||||
},
|
||||
"setup_form": {
|
||||
"more_info": "さらに詳しく"
|
||||
},
|
||||
"media": {
|
||||
"play": "再生 (スペース)",
|
||||
"pause": "一時停止 (スペース)",
|
||||
"back-10s": "10 秒戻る (左矢印キー)",
|
||||
"forward-30s": "30 秒進む",
|
||||
"mute": "ミュート (M)",
|
||||
"unmute": "ミュート解除 (M)",
|
||||
"playback-speed": "再生速度",
|
||||
"loop": "ループ",
|
||||
"disable-loop": "ループを解除",
|
||||
"rotate": "回転",
|
||||
"picture-in-picture": "ピクチャーインピクチャー",
|
||||
"exit-picture-in-picture": "ピクチャーインピクチャーを終了",
|
||||
"fullscreen": "全画面表示 (F)",
|
||||
"exit-fullscreen": "全画面表示を終了",
|
||||
"unsupported-format": "このファイル形式ではメディアプレビューはご利用いただけません:\n{{mime}}",
|
||||
"zoom-to-fit": "ズームして全体を表示",
|
||||
"zoom-reset": "ズーム設定をリセット"
|
||||
},
|
||||
"mermaid": {
|
||||
"placeholder": "マーメイド図の内容を入力するか、以下のサンプル図のいずれかを使用してください。",
|
||||
"sample_diagrams": "サンプル図:",
|
||||
"sample_flowchart": "フローチャート",
|
||||
"sample_class": "クラス図",
|
||||
"sample_sequence": "シーケンス図",
|
||||
"sample_entity_relationship": "ER 図",
|
||||
"sample_state": "状態遷移図",
|
||||
"sample_mindmap": "マインドマップ",
|
||||
"sample_architecture": "アーキテクチャ図",
|
||||
"sample_block": "ブロック図",
|
||||
"sample_c4": "C4 図",
|
||||
"sample_gantt": "ガントチャート",
|
||||
"sample_git": "Git グラフ",
|
||||
"sample_kanban": "カンバン",
|
||||
"sample_packet": "パケット図",
|
||||
"sample_pie": "円グラフ",
|
||||
"sample_quadrant": "4象限図",
|
||||
"sample_radar": "レーダーチャート",
|
||||
"sample_requirement": "要件図",
|
||||
"sample_sankey": "サンキー図",
|
||||
"sample_timeline": "タイムライン",
|
||||
"sample_treemap": "ツリーマップ",
|
||||
"sample_user_journey": "ユーザージャーニー図",
|
||||
"sample_xy": "XY チャート",
|
||||
"sample_venn": "ベン図",
|
||||
"sample_ishikawa": "石川図",
|
||||
"sample_treeview": "ツリービュー",
|
||||
"sample_wardley": "ウォードリーマップ"
|
||||
},
|
||||
"llm_chat": {
|
||||
"placeholder": "メッセージを入力してください…",
|
||||
"send": "送信",
|
||||
"sending": "送信中...",
|
||||
"empty_state": "下記にメッセージを入力して会話を始めましょう。",
|
||||
"searching_web": "ウェブ検索中…",
|
||||
"web_search": "ウェブ検索",
|
||||
"note_tools": "ノートへのアクセス",
|
||||
"sources": "ソース",
|
||||
"extended_thinking": "思考を拡張",
|
||||
"legacy_models": "レガシーモデル",
|
||||
"thinking": "思考中...",
|
||||
"thought_process": "思考プロセス",
|
||||
"tool_calls": "{{count}} 回のツール呼び出し",
|
||||
"input": "入力",
|
||||
"result": "結果",
|
||||
"error": "エラー",
|
||||
"tool_error": "失敗",
|
||||
"total_tokens": "{{total}} トークン",
|
||||
"tokens_detail": "{{prompt}} プロンプト + {{completion}} コンプリーション",
|
||||
"tokens_used": "{{prompt}} プロンプト + {{completion}} コンプリーション = {{total}} トークン",
|
||||
"tokens_used_with_cost": "{{prompt}} プロンプト + {{completion}} コンプリーション = {{total}} トークン (~${{cost}})",
|
||||
"tokens_used_with_model": "{{model}}: {{prompt}} プロンプト + {{completion}} コンプリーション = {{total}} トークン",
|
||||
"tokens_used_with_model_and_cost": "{{model}}: {{prompt}} プロンプト + {{completion}} コンプリーション = {{total}} トークン (~${{cost}})",
|
||||
"tokens": "トークン",
|
||||
"context_used": "{{percentage}} % 使用済み",
|
||||
"note_context_enabled": "クリックしてノートのコンテキストを無効にする: {{title}}",
|
||||
"note_context_disabled": "クリックして現在のノートをコンテキストに含める",
|
||||
"no_provider_message": "AI プロバイダーが設定されていません。チャットを開始するには、プロバイダーを追加してください。",
|
||||
"add_provider": "AI プロバイダーを追加",
|
||||
"sources_summary": "{{count}} 件のソースを {{sites}} サイトから取得"
|
||||
},
|
||||
"sidebar_chat": {
|
||||
"title": "AI チャット",
|
||||
"launcher_title": "AI チャットを開く",
|
||||
"new_chat": "新しいチャットを開始",
|
||||
"save_chat": "チャットをノートに保存",
|
||||
"empty_state": "会話を開始",
|
||||
"history": "チャット履歴",
|
||||
"recent_chats": "最近のチャット",
|
||||
"no_chats": "過去のチャットはありません"
|
||||
},
|
||||
"mind-map": {
|
||||
"addChild": "子ノードを追加",
|
||||
"addParent": "親ノードを追加",
|
||||
"addSibling": "兄弟ノードを追加",
|
||||
"removeNode": "ノードを削除",
|
||||
"focus": "フォーカスモード",
|
||||
"cancelFocus": "フォーカスモードを解除",
|
||||
"moveUp": "上に移動",
|
||||
"moveDown": "下に移動",
|
||||
"link": "リンク",
|
||||
"linkBidirectional": "双方向リンク",
|
||||
"clickTips": "対象ノードをクリックしてください",
|
||||
"summary": "概要"
|
||||
},
|
||||
"llm": {
|
||||
"settings_title": "AI / LLM",
|
||||
"settings_description": "AI と大規模言語モデルの連携設定をします。",
|
||||
"add_provider": "プロバイダーを追加",
|
||||
"add_provider_title": "AI プロバイダーを追加",
|
||||
"configured_providers": "設定済みプロバイダー",
|
||||
"no_providers_configured": "まだプロバイダーが設定されていません。",
|
||||
"provider_name": "名前",
|
||||
"provider_type": "プロバイダー",
|
||||
"actions": "アクション",
|
||||
"delete_provider": "削除",
|
||||
"delete_provider_confirmation": "プロバイダー \"{{name}}\" を削除してもよろしいですか?",
|
||||
"api_key": "API キー",
|
||||
"api_key_placeholder": "API キーを入力してください",
|
||||
"cancel": "キャンセル",
|
||||
"feature_not_enabled": "AI 連携機能を使用するには、「設定」→「高度」→「実験的機能」で LLM 実験的機能を有効にしてください。",
|
||||
"mcp_title": "MCP(モデル コンテキスト プロトコル)",
|
||||
"mcp_enabled": "MCP サーバー",
|
||||
"mcp_enabled_description": "AI コーディングアシスタント(例:Claude Code、GitHub Copilot)がノートを読み取って変更できるように、モデルコンテキストプロトコル(MCP)エンドポイントを公開します。このエンドポイントは localhost からのみアクセス可能です。",
|
||||
"mcp_endpoint_title": "エンドポイント URL",
|
||||
"mcp_endpoint_description": "この URL を AI アシスタントの MCP 設定に追加してください",
|
||||
"tools": {
|
||||
"search_notes": "ノートを検索",
|
||||
"get_note": "ノートを取得",
|
||||
"get_note_content": "ノートの内容を取得",
|
||||
"update_note_content": "ノートの内容を更新",
|
||||
"append_to_note": "ノートに追記",
|
||||
"create_note": "ノートを作成",
|
||||
"get_attributes": "複数の属性を取得",
|
||||
"get_attribute": "属性を取得",
|
||||
"set_attribute": "属性を設定",
|
||||
"delete_attribute": "属性を削除",
|
||||
"get_child_notes": "子ノートを取得",
|
||||
"get_subtree": "サブツリーを取得",
|
||||
"load_skill": "スキルを読み込む",
|
||||
"web_search": "Web 検索",
|
||||
"note_in_parent": "<Note/> を <Parent/>",
|
||||
"get_attachment": "添付ファイルを取得",
|
||||
"get_attachment_content": "添付ファイルの内容を読み取る"
|
||||
}
|
||||
},
|
||||
"ocr": {
|
||||
"extracted_text": "抽出されたテキスト(OCR)",
|
||||
"extracted_text_title": "抽出されたテキスト(OCR)",
|
||||
"loading_text": "OCR テキストを読み込んでいます…",
|
||||
"no_text_available": "OCR テキストが見つかりません",
|
||||
"no_text_explanation": "このノートは OCR テキスト抽出処理が行われなかったか、テキストが見つかりませんでした。",
|
||||
"failed_to_load": "OCR テキストの読み込みに失敗しました",
|
||||
"process_now": "OCR 処理",
|
||||
"processing": "処理中…",
|
||||
"processing_started": "OCR 処理が開始されました。しばらくお待ちいただき、ページを更新してください。",
|
||||
"processing_failed": "OCR 処理の開始に失敗しました",
|
||||
"view_extracted_text": "抽出されたテキスト(OCR)を表示",
|
||||
"processing_complete": "OCR 処理が完了しました。",
|
||||
"text_filtered_low_confidence": "OCR は {{confidence}}% の信頼度でテキストを検出しましたが、最小しきい値が {{threshold}}% であるため、破棄されました。",
|
||||
"open_media_settings": "設定を開く"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
"branch_prefix_saved": "브랜치 접두사가 저장되었습니다.",
|
||||
"edit_branch_prefix_multiple": "{{count}}개의 지점 접두사 편집",
|
||||
"branch_prefix_saved_multiple": "{{count}}개의 지점에 대해 지점 접두사가 저장되었습니다.",
|
||||
"affected_branches": "영향을 받은 분기 수({{count}}):"
|
||||
"affected_branches": "영향을 받는 브랜치 수 ({{count}}):"
|
||||
},
|
||||
"bulk_actions": {
|
||||
"bulk_actions": "대량 작업",
|
||||
@@ -100,6 +100,9 @@
|
||||
"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": "모든 복제본 삭제(최근 변경 사항에서 되돌릴 수 있습니다)"
|
||||
},
|
||||
@@ -131,27 +134,6 @@
|
||||
"notSet": "미설정",
|
||||
"goBackForwards": "히스토리에서 뒤로/앞으로 이동",
|
||||
"showJumpToNoteDialog": "<a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/note-navigation.html#jump-to-note\">\"노트로 이동\" 대화 상자</a> 표시",
|
||||
"scrollToActiveNote": "활성화된 노트로 스크롤 이동",
|
||||
"collapseWholeTree": "모든 노트 트리를 접기",
|
||||
"collapseSubTree": "하위 트리 접기",
|
||||
"tabShortcuts": "탭 단축키",
|
||||
"onlyInDesktop": "데스크톱에서만(일렉트론 빌드)",
|
||||
"openEmptyTab": "빈 탭 열기",
|
||||
"closeActiveTab": "활성 탭 닫기",
|
||||
"jumpToParentNote": "부모 노트로 이동하기",
|
||||
"activateNextTab": "다음 탭 활성화",
|
||||
"activatePreviousTab": "이전 탭 활성화",
|
||||
"creatingNotes": "노트 만들기",
|
||||
"createNoteInto": "활성 노트에 새로운 하위 노트 추가",
|
||||
"movingCloningNotes": "노트 이동/복제",
|
||||
"moveNoteUpDown": "노트 목록에서 노트 위/아래 이동",
|
||||
"selectAllNotes": "현재 레벨의 모든 노트 선택",
|
||||
"selectNote": "노트 선택",
|
||||
"deleteNotes": "노트/하위트리 삭제",
|
||||
"editingNotes": "노트 편집",
|
||||
"createEditLink": "외부 링크 생성/편집",
|
||||
"createInternalLink": "내부 링크 생성",
|
||||
"followLink": "커서아래 링크 따라가기",
|
||||
"insertDateTime": "커서위치에 현재 날짜와 시간 삽입"
|
||||
"scrollToActiveNote": "활성화된 노트로 스크롤 이동"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,8 @@
|
||||
},
|
||||
"delete_notes": {
|
||||
"close": "Lukk",
|
||||
"cancel": "Avbryt"
|
||||
"cancel": "Avbryt",
|
||||
"ok": "OK"
|
||||
},
|
||||
"export": {
|
||||
"close": "Lukk",
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
},
|
||||
"bundle-error": {
|
||||
"title": "Custom script laden mislukt",
|
||||
"message": "Script voor de notitie met ID \"{{id}}\", getiteld \"{{title}}\" kon niet worden uitgevoerd vanwege:\n\n{{message}}"
|
||||
"message": "Script van notitie met ID \"{{id}}\", getiteld \"{{title}}\" kon niet worden uitgevoerd vanwege:\n\n{{message}}"
|
||||
},
|
||||
"scripting-error": "Error met script: {{title}}",
|
||||
"widget-list-error": {
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
"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}}”.\n\nJeśli skrypt ma działać bez interfejsu użytkownika (UI) wyłącz go: '#run=frontendStartup'.",
|
||||
"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}}"
|
||||
},
|
||||
@@ -78,12 +78,15 @@
|
||||
"delete_notes": {
|
||||
"cancel": "Anuluj",
|
||||
"close": "Zamknij",
|
||||
"delete_notes_preview": "Podgląd usuwania notatek",
|
||||
"delete_all_clones_description": "Usuń również wszystkie klony (można cofnąć w oknie Ostatnie zmiany)",
|
||||
"erase_notes_description": "Normalne (miękkie) usuwanie jedynie oznacza notatki jako usunięte i można je przywrócić (w oknie Ostatnie zmiany) przez pewien czas. Zaznaczenie tej opcji spowoduje natychmiastowe wymazanie notatek i nie będzie możliwe ich przywrócenie.",
|
||||
"erase_notes_warning": "Wymaż notatki trwale (nie można cofnąć), w tym wszystkie klony. Wymusi to przeładowanie aplikacji.",
|
||||
"notes_to_be_deleted": "Następujące notatki zostaną usunięte ({{notesCount}})",
|
||||
"no_note_to_delete": "Żadna notatka nie zostanie usunięta (tylko klony).",
|
||||
"broken_relations_to_be_deleted": "Następujące relacje zostaną zerwane i usunięte ({{ relationCount}})"
|
||||
"broken_relations_to_be_deleted": "Następujące relacje zostaną zerwane i usunięte ({{ relationCount}})",
|
||||
"ok": "OK",
|
||||
"deleted_relation_text": "Notatka {{- note}} (do usunięcia) jest powiązana relacją {{- relation}} pochodzącą z {{- source}}."
|
||||
},
|
||||
"export": {
|
||||
"close": "Zamknij",
|
||||
@@ -114,7 +117,7 @@
|
||||
"no_path_to_clone_to": "Brak ścieżki do sklonowania.",
|
||||
"note_cloned": "Notatka \"{{clonedTitle}}\" została sklonowana do \"{{targetTitle}}\"",
|
||||
"help_on_links": "Pomoc dotycząca linków",
|
||||
"target_parent_note": "Docelowa notatka pierwotna"
|
||||
"target_parent_note": "Docelowa notatka nadrzędna"
|
||||
},
|
||||
"help": {
|
||||
"title": "Ściągawka",
|
||||
@@ -123,7 +126,7 @@
|
||||
"collapseExpand": "zwiń/rozwiń węzeł",
|
||||
"notSet": "nie ustawiono",
|
||||
"goBackForwards": "idź wstecz / do przodu w historii",
|
||||
"showJumpToNoteDialog": "pokaż <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/note-navigation.html#jump-to-note\">\"Przejdź do\"</a>",
|
||||
"showJumpToNoteDialog": "pokaż okno <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/note-navigation.html#jump-to-note\">\"Przejdź do\"</a>",
|
||||
"scrollToActiveNote": "przewiń do aktywnej notatki",
|
||||
"jumpToParentNote": "przejdź do notatki nadrzędnej",
|
||||
"collapseWholeTree": "zwiń całe drzewo notatek",
|
||||
@@ -399,8 +402,7 @@
|
||||
"and_more": "... i {{count}} więcej.",
|
||||
"print_landscape": "Podczas eksportowania do PDF zmienia orientację strony na poziomą zamiast pionowej.",
|
||||
"print_page_size": "Podczas eksportowania do PDF zmienia rozmiar strony. Obsługiwane wartości: <code>A0</code>, <code>A1</code>, <code>A2</code>, <code>A3</code>, <code>A4</code>, <code>A5</code>, <code>A6</code>, <code>Legal</code>, <code>Letter</code>, <code>Tabloid</code>, <code>Ledger</code>.",
|
||||
"color_type": "Kolor",
|
||||
"textarea": "Wiele linii tekstu"
|
||||
"color_type": "Kolor"
|
||||
},
|
||||
"import": {
|
||||
"importIntoNote": "Importuj do notatki",
|
||||
@@ -1273,6 +1275,7 @@
|
||||
"unprotecting-title": "Status zdejmowania ochrony"
|
||||
},
|
||||
"relation_map": {
|
||||
"open_in_new_tab": "Otwórz w nowej karcie",
|
||||
"remove_note": "Usuń notatkę",
|
||||
"edit_title": "Edytuj tytuł",
|
||||
"rename_note": "Zmień nazwę notatki",
|
||||
@@ -1484,7 +1487,7 @@
|
||||
"custom_name_label": "Nazwa niestandardowej wyszukiwarki",
|
||||
"custom_name_placeholder": "Dostosuj nazwę wyszukiwarki",
|
||||
"custom_url_label": "URL niestandardowej wyszukiwarki powinien zawierać {keyword} jako symbol zastępczy dla wyszukiwanej frazy.",
|
||||
"custom_url_placeholder": "Dostosuj url wyszukiwarki",
|
||||
"custom_url_placeholder": "Dostosuj URL wyszukiwarki",
|
||||
"save_button": "Zapisz"
|
||||
},
|
||||
"tray": {
|
||||
@@ -1611,7 +1614,7 @@
|
||||
"password_changed_success": "Hasło zostało zmienione. Trilium zostanie przeładowane po naciśnięciu OK."
|
||||
},
|
||||
"multi_factor_authentication": {
|
||||
"title": "Uwierzytelnianie wieloskładnikowe",
|
||||
"title": "Uwierzytelnianie wieloskładnikowe (MFA)",
|
||||
"description": "Uwierzytelnianie wieloskładnikowe (MFA) dodaje dodatkową warstwę zabezpieczeń do Twojego konta. Zamiast tylko wpisywać hasło do logowania, MFA wymaga podania jednego lub więcej dodatkowych dowodów tożsamości. W ten sposób, nawet jeśli ktoś zdobędzie Twoje hasło, nadal nie będzie mógł uzyskać dostępu do Twojego konta bez drugiej informacji. To jak dodanie dodatkowego zamka do drzwi, utrudniającego włamanie.<br><br>Proszę postępować zgodnie z poniższymi instrukcjami, aby włączyć MFA. Jeśli nie skonfigurujesz poprawnie, logowanie powróci do samego hasła.",
|
||||
"mfa_enabled": "Włącz uwierzytelnianie wieloskładnikowe",
|
||||
"mfa_method": "Metoda MFA",
|
||||
@@ -1626,7 +1629,7 @@
|
||||
"totp_secret_generated": "Sekret TOTP wygenerowany",
|
||||
"totp_secret_warning": "Proszę zapisać wygenerowany sekret w bezpiecznym miejscu. Nie zostanie pokazany ponownie.",
|
||||
"totp_secret_regenerate_confirm": "Czy na pewno chcesz ponownie wygenerować sekret TOTP? To unieważni poprzedni sekret TOTP i wszystkie istniejące kody odzyskiwania.",
|
||||
"recovery_keys_title": "Klucze odzyskiwania logowania jednokrotnego",
|
||||
"recovery_keys_title": "Klucze odzyskiwania logowania jednokrotnego (SSO)",
|
||||
"recovery_keys_description": "Klucze odzyskiwania logowania jednokrotnego służą do logowania w przypadku braku dostępu do kodów Authenticator.",
|
||||
"recovery_keys_description_warning": "Klucze odzyskiwania nie zostaną pokazane ponownie po opuszczeniu strony, przechowuj je w bezpiecznym miejscu.<br>Po użyciu klucza odzyskiwania nie można go użyć ponownie.",
|
||||
"recovery_keys_error": "Błąd generowania kodów odzyskiwania",
|
||||
@@ -1662,12 +1665,16 @@
|
||||
"description": "Te opcje dotyczą tylko wersji desktopowych, przeglądarki będą używać własnego natywnego sprawdzania pisowni.",
|
||||
"enable": "Włącz sprawdzanie pisowni",
|
||||
"language_code_label": "Kod(y) języka",
|
||||
"language_code_placeholder": "na przykład \"pl-PL\", \"en-US\"",
|
||||
"multiple_languages_info": "Wiele języków można oddzielić przecinkiem, np. \"en-US, de-DE, pl\". ",
|
||||
"available_language_codes_label": "Dostępne kody języków:",
|
||||
"restart-required": "Zmiany w opcjach sprawdzania pisowni wejdą w życie po ponownym uruchomieniu aplikacji."
|
||||
},
|
||||
"sync_2": {
|
||||
"config_title": "Konfiguracja synchronizacji",
|
||||
"server_address": "Adres instancji serwera",
|
||||
"timeout": "Limit czasu synchronizacji",
|
||||
"timeout_unit": "milisekund",
|
||||
"proxy_label": "Serwer proxy synchronizacji (opcjonalnie)",
|
||||
"note": "Uwaga",
|
||||
"note_description": "Jeśli pozostawisz ustawienie proxy puste, zostanie użyte proxy systemowe (dotyczy tylko wersji desktop/electron).",
|
||||
@@ -1760,7 +1767,7 @@
|
||||
"book": "Kolekcja",
|
||||
"mermaid-diagram": "Diagram Mermaid",
|
||||
"canvas": "Płótno",
|
||||
"web-view": "Widok strony web",
|
||||
"web-view": "Widok WWW",
|
||||
"mind-map": "Mapa myśli",
|
||||
"file": "Plik",
|
||||
"image": "Obraz",
|
||||
@@ -1809,9 +1816,9 @@
|
||||
"modal_title": "Konfiguracja listy wyróżnień",
|
||||
"menu_configure": "Konfiguracja listy wyróżnień...",
|
||||
"no_highlights": "Nie znaleziono wyróżnień.",
|
||||
"title_with_count_one": "{{count}} wyróżnienie",
|
||||
"title_with_count_few": "{{count}} wyróżnienia",
|
||||
"title_with_count_many": "{{count}} wyróżnień"
|
||||
"title_with_count_one": "{{count}} podświetlenie",
|
||||
"title_with_count_few": "{{count}} podświetlenia",
|
||||
"title_with_count_many": "{{count}} podświetleń"
|
||||
},
|
||||
"quick-search": {
|
||||
"placeholder": "Szybkie wyszukiwanie",
|
||||
@@ -2064,7 +2071,7 @@
|
||||
"read_only_temporarily_disabled_description": "Ta notatka jest obecnie edytowalna, ale normalnie jest tylko do odczytu. Notatka powróci do trybu tylko do odczytu, gdy tylko przejdziesz do innej notatki.\n\nKliknij, aby ponownie włączyć tryb tylko do odczytu.",
|
||||
"shared_publicly": "Udostępniona publicznie",
|
||||
"shared_locally": "Udostępniona lokalnie",
|
||||
"clipped_note": "Wycinek z sieci",
|
||||
"clipped_note": "Wycinek WWW",
|
||||
"clipped_note_description": "Ta notatka została pierwotnie pobrana z {{url}}.\n\nKliknij, aby przejść do źródłowej strony internetowej.",
|
||||
"execute_script": "Uruchom skrypt",
|
||||
"execute_script_description": "Ta notatka jest notatką skryptową. Kliknij, aby wykonać skrypt.",
|
||||
@@ -2191,52 +2198,5 @@
|
||||
},
|
||||
"setup_form": {
|
||||
"more_info": "Dowiedz się więcej"
|
||||
},
|
||||
"media": {
|
||||
"fullscreen": "Pełny ekran (F)",
|
||||
"mute": "Wycisz (M)",
|
||||
"unmute": "Wyłącz wyciszenie (M)",
|
||||
"exit-fullscreen": "Wyłącz pełny ekran",
|
||||
"loop": "Pętla",
|
||||
"disable-loop": "Wyłącz pętle",
|
||||
"rotate": "Obróć",
|
||||
"picture-in-picture": "Obraz w obrazie",
|
||||
"pause": "Zatrzymaj (Space)",
|
||||
"back-10s": "Cofnij 10s (Lewa strzałka)",
|
||||
"forward-30s": "Do przodu 30s",
|
||||
"playback-speed": "Szybkość odtwarzania",
|
||||
"exit-picture-in-picture": "Wyjdź z obrazu w obrazie",
|
||||
"zoom-to-fit": "Powiększ aby wypełnić",
|
||||
"unsupported-format": "Podgląd multimediów nie jest dostępny dla tego formatu pliku\n{{mime}}",
|
||||
"play": "Odtwórz (Space)",
|
||||
"zoom-reset": "Zresetuj powiększenie"
|
||||
},
|
||||
"mermaid": {
|
||||
"sample_architecture": "Architektura",
|
||||
"sample_diagrams": "Przykład diagramu:",
|
||||
"sample_flowchart": "Schemat blokowy",
|
||||
"sample_class": "Klasa",
|
||||
"sample_sequence": "Sekwencja",
|
||||
"sample_timeline": "Oś czasu",
|
||||
"sample_treemap": "Mapa drzewa",
|
||||
"sample_xy": "XY",
|
||||
"sample_venn": "Diagram Venna",
|
||||
"sample_ishikawa": "Diagram Ishikawa",
|
||||
"placeholder": "Wpisz treść swojego diagramu lub skorzystaj z jednego z przykładowych diagramów poniżej.",
|
||||
"sample_entity_relationship": "Diagram związków encji",
|
||||
"sample_state": "Diagram stanów",
|
||||
"sample_mindmap": "Mapa myśli",
|
||||
"sample_block": "Diagram blokowy",
|
||||
"sample_c4": "C4",
|
||||
"sample_gantt": "Wykres Gantta",
|
||||
"sample_git": "Diagram Git",
|
||||
"sample_kanban": "Tablica Kanban",
|
||||
"sample_packet": "Diagram pakietów",
|
||||
"sample_pie": "Wykres kołowy",
|
||||
"sample_quadrant": "Diagram kwadrantowy",
|
||||
"sample_radar": "Wykres radarowy",
|
||||
"sample_requirement": "Diagram wymagań",
|
||||
"sample_sankey": "Wykres Sankeya",
|
||||
"sample_user_journey": "Mapa Podróży Użytkownika"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
"also_delete_note": "Também apagar a nota"
|
||||
},
|
||||
"delete_notes": {
|
||||
"delete_notes_preview": "Apagar pré-visualização de notas",
|
||||
"close": "Fechar",
|
||||
"delete_all_clones_description": "Apagar também todos os clones (pode ser desfeito em alterações recentes)",
|
||||
"erase_notes_description": "Apagar normal (suave) apenas marca as notas como apagadas, permitindo que sejam recuperadas (no diálogo de alterações recentes) num período. Se esta opção for marcada, as notas serão apagadas imediatamente e não será possível restaurá-las.",
|
||||
@@ -95,7 +96,9 @@
|
||||
"notes_to_be_deleted": "As seguintes notas serão apagadas ({{notesCount}})",
|
||||
"no_note_to_delete": "Nenhuma nota será apagada (apenas os clones).",
|
||||
"broken_relations_to_be_deleted": "As seguintes relações serão quebradas e apagadas ({{ relationCount}})",
|
||||
"cancel": "Cancelar"
|
||||
"cancel": "Cancelar",
|
||||
"ok": "OK",
|
||||
"deleted_relation_text": "A nota {{- note}} (a ser apagada) está referenciada pela relação {{- relation}} originada de {{- source}}."
|
||||
},
|
||||
"export": {
|
||||
"export_note_title": "Exportar nota",
|
||||
@@ -1044,6 +1047,7 @@
|
||||
"unprotecting-title": "Estado da remoção de proteção"
|
||||
},
|
||||
"relation_map": {
|
||||
"open_in_new_tab": "Abrir em nova guia",
|
||||
"remove_note": "Remover nota",
|
||||
"edit_title": "Editar título",
|
||||
"rename_note": "Renomear nota",
|
||||
@@ -1432,12 +1436,16 @@
|
||||
"description": "Estas opções aplicam-se apenas às versões desktop; os navegadores usarão a sua própria verificação ortográfica nativa.",
|
||||
"enable": "Ativar verificação ortográfica",
|
||||
"language_code_label": "Código(s) de idioma",
|
||||
"language_code_placeholder": "por exemplo \"en-US\", \"de-AT\", \"pt-BR\"",
|
||||
"multiple_languages_info": "Múltiplos idiomas podem ser separados por vírgula, por exemplo: \"en-US, de-DE, pt-BR, cs\". ",
|
||||
"available_language_codes_label": "Códigos de idioma disponíveis:",
|
||||
"restart-required": "As alterações nas opções de verificação ortográfica terão efeito após reiniciar a aplicação."
|
||||
},
|
||||
"sync_2": {
|
||||
"config_title": "Configuração da Sincronização",
|
||||
"server_address": "Endereço da instância do Servidor",
|
||||
"timeout": "Tempo limite da sincronização",
|
||||
"timeout_unit": "milisegundos",
|
||||
"proxy_label": "Servidor proxy para sincronização (opcional)",
|
||||
"note": "Nota",
|
||||
"note_description": "Se deixar a configuração de proxy em branco, o proxy do sistema será usado (aplica-se apenas à versão desktop/Electron).",
|
||||
|
||||
@@ -94,6 +94,7 @@
|
||||
"also_delete_note": "Também excluir a nota"
|
||||
},
|
||||
"delete_notes": {
|
||||
"delete_notes_preview": "Excluir pré-visualização de notas",
|
||||
"close": "Fechar",
|
||||
"delete_all_clones_description": "Excluir também todos os clones (pode ser desfeito em alterações recentes)",
|
||||
"erase_notes_description": "A exclusão normal (suave) apenas marca as notas como excluídas, permitindo que sejam recuperadas (no diálogo de alterações recentes) dentro de um período de tempo. Se esta opção for marcada, as notas serão apagadas imediatamente e não será possível restaurá-las.",
|
||||
@@ -101,7 +102,9 @@
|
||||
"notes_to_be_deleted": "As seguintes notas serão excluídas ({{notesCount}})",
|
||||
"no_note_to_delete": "Nenhuma nota será excluída (apenas os clones).",
|
||||
"broken_relations_to_be_deleted": "As seguintes relações serão quebradas e excluídas ({{ relationCount}})",
|
||||
"cancel": "Cancelar"
|
||||
"cancel": "Cancelar",
|
||||
"ok": "OK",
|
||||
"deleted_relation_text": "A nota {{- note}} (a ser excluída) está referenciada pela relação {{- relation}} originada de {{- source}}."
|
||||
},
|
||||
"export": {
|
||||
"export_note_title": "Exportar nota",
|
||||
@@ -1108,6 +1111,7 @@
|
||||
"start_session_button": "Iniciar sessão protegida"
|
||||
},
|
||||
"relation_map": {
|
||||
"open_in_new_tab": "Abrir em nova aba",
|
||||
"remove_note": "Remover nota",
|
||||
"edit_title": "Editar título",
|
||||
"rename_note": "Renomear nota",
|
||||
@@ -1941,12 +1945,16 @@
|
||||
"description": "Estas opções se aplicam apenas às versões desktop; os navegadores usarão sua própria verificação ortográfica nativa.",
|
||||
"enable": "Habilitar verificação ortográfica",
|
||||
"language_code_label": "Código(s) de idioma",
|
||||
"language_code_placeholder": "por exemplo \"en-US\", \"de-AT\", \"pt-BR\"",
|
||||
"multiple_languages_info": "Múltiplos idiomas podem ser separados por vírgula, por exemplo: \"en-US, de-DE, pt-BR, cs\". ",
|
||||
"available_language_codes_label": "Códigos de idioma disponíveis:",
|
||||
"restart-required": "As alterações nas opções de verificação ortográfica terão efeito após reiniciar o aplicativo."
|
||||
},
|
||||
"sync_2": {
|
||||
"config_title": "Configuração da Sincronização",
|
||||
"server_address": "Endereço da instância do Servidor",
|
||||
"timeout": "Tempo limite da sincronização",
|
||||
"timeout_unit": "milisegundos",
|
||||
"proxy_label": "Servidor proxy para sincronização (opcional)",
|
||||
"note": "Nota",
|
||||
"note_description": "Se você deixar a configuração de proxy em branco, o proxy do sistema será usado (aplica-se apenas à versão desktop/Electron).",
|
||||
|
||||
@@ -459,10 +459,13 @@
|
||||
"broken_relations_to_be_deleted": "Următoarele relații vor fi întrerupte și șterse ({{ relationCount}})",
|
||||
"cancel": "Anulează",
|
||||
"delete_all_clones_description": "Șterge și toate clonele (se pot recupera în ecranul Schimbări recente)",
|
||||
"delete_notes_preview": "Previzualizare ștergerea notițelor",
|
||||
"erase_notes_description": "Ștergerea obișnuită doar marchează notițele ca fiind șterse și pot fi recuperate (în ecranul Schimbări recente) pentru o perioadă de timp. Dacă se bifează această opțiune, notițele vor fi șterse imediat fără posibilitatea de a le recupera.",
|
||||
"erase_notes_warning": "Șterge notițele permanent (nu se mai pot recupera), incluzând toate clonele. Va forța reîncărcarea aplicației.",
|
||||
"no_note_to_delete": "Nicio notiță nu va fi ștearsă (doar clonele).",
|
||||
"notes_to_be_deleted": "Următoarele notițe vor fi șterse ({{notesCount}})",
|
||||
"ok": "OK",
|
||||
"deleted_relation_text": "Notița {{- note}} ce va fi ștearsă este referențiată de relația {{- relation}}, originând din {{- source}}.",
|
||||
"close": "Închide"
|
||||
},
|
||||
"delete_relation": {
|
||||
@@ -872,7 +875,7 @@
|
||||
"print_note": "Imprimare notiță",
|
||||
"re_render_note": "Reinterpretare notiță",
|
||||
"save_revision": "Salvează o nouă revizie",
|
||||
"advanced": "Avansat",
|
||||
"advanced": "Advansat",
|
||||
"search_in_note": "Caută în notiță",
|
||||
"convert_into_attachment_failed": "Nu s-a putut converti notița „{{title}}”.",
|
||||
"convert_into_attachment_successful": "Notița „{{title}}” a fost convertită în atașament.",
|
||||
@@ -1051,6 +1054,7 @@
|
||||
"enter_title_of_new_note": "Introduceți titlul noii notițe",
|
||||
"note_already_in_diagram": "Notița „{{title}}” deja se află pe diagramă.",
|
||||
"note_not_found": "Notița „{{noteId}}” nu a putut fi găsită!",
|
||||
"open_in_new_tab": "Deschide într-un tab nou",
|
||||
"remove_note": "Șterge notița",
|
||||
"remove_relation": "Șterge relația",
|
||||
"rename_note": "Redenumește notița",
|
||||
@@ -1234,9 +1238,12 @@
|
||||
"title": "titlu"
|
||||
},
|
||||
"spellcheck": {
|
||||
"available_language_codes_label": "Coduri de limbă disponibile:",
|
||||
"description": "Aceste opțiuni se aplică doar pentru aplicația de desktop, navigatoarele web folosesc propriile corectoare ortografice.",
|
||||
"enable": "Activează corectorul ortografic",
|
||||
"language_code_label": "Codurile de limbă",
|
||||
"language_code_placeholder": "de exemplu „en-US”, „de-AT”",
|
||||
"multiple_languages_info": "Mai multe limbi pot fi separate prin virgulă, e.g. \"en-US, de-DE, cs\". ",
|
||||
"title": "Corector ortografic",
|
||||
"restart-required": "Schimbările asupra setărilor corectorului ortografic vor fi aplicate după restartarea aplicației."
|
||||
},
|
||||
@@ -1263,7 +1270,8 @@
|
||||
"test_button": "Probează sincronizarea",
|
||||
"test_description": "Această opțiune va testa conexiunea și comunicarea cu serverul de sincronizare. Dacă serverul de sincronizare nu este inițializat, acest lucru va rula și o sincronizare cu documentul local.",
|
||||
"test_title": "Probează sincronizarea",
|
||||
"timeout": "Timp limită de sincronizare"
|
||||
"timeout": "Timp limită de sincronizare",
|
||||
"timeout_unit": "milisecunde"
|
||||
},
|
||||
"table_of_contents": {
|
||||
"description": "Cuprinsul va apărea în notițele de tip text atunci când notița are un număr de titluri mai mare decât cel definit. Acest număr se poate personaliza:",
|
||||
|
||||
@@ -83,7 +83,10 @@
|
||||
"notes_to_be_deleted": "Следующие заметки будут удалены ({{notesCount}})",
|
||||
"no_note_to_delete": "Заметка не будет удалена (только клоны).",
|
||||
"broken_relations_to_be_deleted": "Следующие отношения будут разорваны и удалены ({{relationCount}})",
|
||||
"cancel": "Отмена"
|
||||
"cancel": "Отмена",
|
||||
"ok": "ОК",
|
||||
"deleted_relation_text": "Примечание {{- note}} (подлежит удалению) ссылается на отношение {{- relation}}, происходящее из {{- source}}.",
|
||||
"delete_notes_preview": "Предпросмотр удаляемых заметок"
|
||||
},
|
||||
"database_anonymization": {
|
||||
"light_anonymization_description": "Это действие создаст новую копию базы данных и выполнит её лёгкую анонимизацию — в частности, будет удалён только контент всех заметок, но заголовки и атрибуты останутся. Кроме того, будут сохранены пользовательские заметки, содержащие JavaScript-скрипты frontend/backend и пользовательские виджеты. Это даёт больше контекста для отладки проблем.",
|
||||
@@ -191,7 +194,7 @@
|
||||
"row-insert-child": "Создать дочернюю заметку",
|
||||
"row-insert-below": "Добавить строку ниже",
|
||||
"row-insert-above": "Добавить строку выше",
|
||||
"new-column-relation": "Отношение"
|
||||
"new-column-relation": "Связь"
|
||||
},
|
||||
"add_label": {
|
||||
"add_label": "Добавить метку",
|
||||
@@ -462,13 +465,13 @@
|
||||
"related_notes_title": "Другие заметки с этой меткой",
|
||||
"label": "Метка",
|
||||
"label_definition": "Определение метки",
|
||||
"relation": "Детали отношения",
|
||||
"relation": "Отношение",
|
||||
"relation_definition": "Определение отношения",
|
||||
"disable_versioning": "отключает автоматическое версионирование. Полезно, например, для больших, но неважных заметок, например, для больших JS-библиотек, используемых для написания скриптов",
|
||||
"calendar_root": "отмечает заметку, которая должна использоваться в качестве корневой для заметок дня. Только одна должна быть отмечена как таковая.",
|
||||
"archived": "заметки с этой меткой не будут отображаться в результатах поиска по умолчанию (а также в диалоговых окнах «Перейти к», «Добавить ссылку» и т. д.).",
|
||||
"exclude_from_export": "заметки (с их поддеревьями) не будут включены ни в один экспорт заметок",
|
||||
"run": "определяет, при каких событиях должен запускаться скрипт. Возможные значения:\n<ul>\n<li>frontendStartup — при запуске (или обновлении) фронтенда Trilium, но не на мобильном устройстве.</li>\n<li>mobileStartup — при запуске (или обновлении) фронтенда Trilium на мобильном устройстве.</li>\n<li>backendStartup — при запуске бэкенда Trilium.</li>\n<li>hourly — запускать каждый час. Для указания времени можно использовать дополнительную метку <code>runAtHour</code>.</li>\n<li>daily — запускать раз в день.</li>\n</ul>",
|
||||
"run": "определяет, при каких событиях должен запускаться скрипт. Возможные значения:<ul>\n<li>frontendStartup — при запуске (или обновлении) фронтенда Trilium, но не на мобильном устройстве.</li>\n<li>mobileStartup — при запуске (или обновлении) фронтенда Trilium на мобильном устройстве.</li>\n<li>backendStartup — при запуске бэкенда Trilium.</li>\n<li>hourly — запускать каждый час. Для указания времени можно использовать дополнительную метку <code>runAtHour</code>.</li>\n<li>daily — запускать раз в день.</li></ul>",
|
||||
"run_on_instance": "Определить, на каком экземпляре Trilium это должно выполняться. По умолчанию — для всех экземпляров.",
|
||||
"run_at_hour": "В какой час это должно выполняться? Следует использовать вместе с <code>#run=hourly</code>. Можно задать несколько раз для большего количества запусков в течение дня.",
|
||||
"disable_inclusion": "скрипты с этой меткой не будут включены в выполнение родительского скрипта.",
|
||||
@@ -492,7 +495,7 @@
|
||||
"is_owned_by_note": "принадлежит заметке",
|
||||
"and_more": "... и ещё {{count}}.",
|
||||
"app_theme": "отмечает заметки CSS, которые являются полноценными темами Trilium и, таким образом, доступны в опциях Trilium.",
|
||||
"title_template": "заголовок по умолчанию для заметок, создаваемых как дочерние элементы текущей. Значение вычисляется как строка JavaScript \n и может быть дополнено динамическим контентом с помощью внедренных переменных <code>now</code> и <code>parentNote</code>. Например:\n \n <ul>\n <li><code>Литературные произведения ${parentNote.getLabelValue('authorName')}</code></li>\n <li><code>Лог для ${now.format('YYYY-MM-DD HH:mm:ss')}</code></li>\n </ul>\n \n Подробности см. в <a href=\"https://triliumnext.github.io/Docs/Wiki/default-note-title.html\">вики</a>, документации API для <a href=\"https://zadam.github.io/trilium/backend_api/Note.html\">parentNote</a> и <a href=\"https://day.js.org/docs/en/display/format\">now</a>.",
|
||||
"title_template": "Заголовок по умолчанию для заметок, создаваемых как дочерние элементы данной заметки. Значение вычисляется как строка JavaScript\n и, таким образом, может быть дополнено динамическим контентом с помощью внедренных переменных <code>now</code> и <code>parentNote</code>. Примеры:\n \n <ul>\n <li><code>Литературные произведения ${parentNote.getLabelValue('authorName')}</code></li>\n <li><code>Лог для ${now.format('YYYY-MM-DD HH:mm:ss')}</code></li>\n </ul>\n \n Подробности см. в <a href=\"https://triliumnext.github.io/Docs/Wiki/default-note-title.html\">вики</a>, документации API для <a href=\"https://zadam.github.io/trilium/backend_api/Note.html\">parentNote</a> и <a href=\"https://day.js.org/docs/en/display/format\">now</a>.",
|
||||
"icon_class": "значение этой метки добавляется в виде CSS-класса к значку в дереве, что помогает визуально различать заметки в дереве. Примером может служить bx bx-home — значки берутся из boxicons. Может использоваться в шаблонах заметок.",
|
||||
"share_favicon": "Заметка о фавиконе должна быть размещена на странице общего доступа. Обычно её назначают корневой папке общего доступа и делают наследуемой. Заметка о фавиконе также должна находиться в поддереве общего доступа. Рассмотрите возможность использования атрибута 'share_hidden_from_tree'.",
|
||||
"inbox": "расположение папки «Входящие» по умолчанию для новых заметок — при создании заметки с помощью кнопки «Новая заметка» на боковой панели заметки будут созданы как дочерние заметки в заметке, помеченной меткой <code>#inbox</code>.",
|
||||
@@ -545,8 +548,7 @@
|
||||
"render_note": "заметки типа «Рендер HTML» будут отображаться с использованием кодовой заметки (HTML или скрипта), и необходимо указать с помощью этой связи, какую заметку следует отобразить",
|
||||
"widget_relation": "заметка, на которую ссылается отношение будет выполнена и отображена как виджет на боковой панели",
|
||||
"share_js": "JavaScript-заметка, которая будет добавлена на страницу общего доступа. JavaScript-заметка также должна находиться в общем поддереве. Рекомендуется использовать 'share_hidden_from_tree'.",
|
||||
"other_notes_with_name": "Другие заметки с {{attributeType}} названием \"{{attributeName}}\"",
|
||||
"textarea": "Многострочный текст"
|
||||
"other_notes_with_name": "Другие заметки с {{attributeType}} названием \"{{attributeName}}\""
|
||||
},
|
||||
"command_palette": {
|
||||
"configure_launch_bar_description": "Откройте конфигурацию панели запуска, чтобы добавить или удалить элементы.",
|
||||
@@ -833,8 +835,7 @@
|
||||
"task-list": "Список задач",
|
||||
"confirm-change": "Не рекомендуется менять тип заметки, если её содержимое не пустое. Вы всё равно хотите продолжить?",
|
||||
"ai-chat": "Чат с ИИ",
|
||||
"spreadsheet": "Электронная таблица",
|
||||
"llm-chat": "Чат с ИИ"
|
||||
"spreadsheet": "Электронная таблица"
|
||||
},
|
||||
"tree-context-menu": {
|
||||
"open-in-popup": "Быстрое редактирование",
|
||||
@@ -1014,7 +1015,7 @@
|
||||
"open_sql_console_history": "Открыть историю консоли SQL",
|
||||
"show_shared_notes_subtree": "Поддерево общедоступных заметок",
|
||||
"switch_to_mobile_version": "Перейти на мобильную версию",
|
||||
"switch_to_desktop_version": "Переключиться на версию для компьютера",
|
||||
"switch_to_desktop_version": "Переключиться на версию для ПК",
|
||||
"new-version-available": "Доступно обновление",
|
||||
"download-update": "Обновить до {{latestVersion}}",
|
||||
"search_notes": "Поиск заметок"
|
||||
@@ -1416,6 +1417,7 @@
|
||||
"no_results": "Не найдено ярлыков, соответствующих '{{filter}}'"
|
||||
},
|
||||
"sync_2": {
|
||||
"timeout_unit": "миллисекунд",
|
||||
"note": "Заметка",
|
||||
"save": "Сохранить",
|
||||
"help": "Помощь",
|
||||
@@ -1623,6 +1625,7 @@
|
||||
"rename_note": "Переименовать заметку",
|
||||
"remove_relation": "Удалить отношение",
|
||||
"default_new_note_title": "новая заметка",
|
||||
"open_in_new_tab": "Открыть в новой вкладке",
|
||||
"confirm_remove_relation": "Вы уверены, что хотите удалить связь?",
|
||||
"enter_new_title": "Введите новое название заметки:",
|
||||
"note_not_found": "Заметка {{noteId}} не найдена!",
|
||||
@@ -1635,11 +1638,11 @@
|
||||
"start_dragging_relations": "Начните перетягивать отношения отсюда на другую заметку."
|
||||
},
|
||||
"vacuum_database": {
|
||||
"title": "Уменьшение размера файла базы данных",
|
||||
"description": "Это приведет к перестройке базы данных, что, скорее всего, уменьшит размер её файла. Данные не будут изменены.",
|
||||
"button_text": "Уменьшить размер файла базы данных",
|
||||
"vacuuming_database": "Уменьшение размера файла базы данных...",
|
||||
"database_vacuumed": "База данных была перестроена"
|
||||
"title": "Сжатие базы данных",
|
||||
"description": "Это приведет к перестройке базы данных, что, как правило, приводит к уменьшению размера файла базы данных. Данные затронуты не будут.",
|
||||
"button_text": "Сжать базу данных",
|
||||
"vacuuming_database": "Сжатие БД...",
|
||||
"database_vacuumed": "База данных была сжата"
|
||||
},
|
||||
"vim_key_bindings": {
|
||||
"use_vim_keybindings_in_code_notes": "Сочетания клавиш Vim",
|
||||
@@ -1675,7 +1678,10 @@
|
||||
"title": "Проверка орфографии",
|
||||
"enable": "Включить проверку орфографии",
|
||||
"language_code_label": "Код(ы) языков",
|
||||
"multiple_languages_info": "Несколько языков можно разделять запятой, например, \"en-US, de-DE, cs\". ",
|
||||
"available_language_codes_label": "Доступные коды языков:",
|
||||
"restart-required": "Изменения параметров проверки орфографии вступят в силу после перезапуска приложения.",
|
||||
"language_code_placeholder": "например \"en-US\", \"de-AT\"",
|
||||
"description": "Эти параметры применимы только для десктопных сборок, браузеры будут использовать собственную встроенную проверку орфографии."
|
||||
},
|
||||
"attribute_editor": {
|
||||
@@ -1758,8 +1764,8 @@
|
||||
"database_integrity_check": {
|
||||
"title": "Проверка целостности базы данных",
|
||||
"description": "Это позволит проверить базу данных на предмет повреждений на уровне SQLite. Это может занять некоторое время в зависимости от размера базы данных.",
|
||||
"check_button": "Проверить целостность базы данных",
|
||||
"checking_integrity": "Проверка целостности базы данных...",
|
||||
"check_button": "Проверить целостность БД",
|
||||
"checking_integrity": "Проверка целостности БД...",
|
||||
"integrity_check_succeeded": "Проверка целостности прошла успешно - проблем не обнаружено.",
|
||||
"integrity_check_failed": "Проверка целостности завершена с ошибками: {{results}}"
|
||||
},
|
||||
@@ -2110,9 +2116,7 @@
|
||||
"new_layout_description": "Попробуйте новый современный и удобный дизайн. В будущих обновлениях возможны его существенные изменения.",
|
||||
"new_layout_name": "Новый дизайн",
|
||||
"title": "Экспериментальные параметры",
|
||||
"disclaimer": "Эти параметры экспериментальные и могут повлиять на стабильность. Используйте с осторожностью.",
|
||||
"llm_name": "ИИ / LLM чат",
|
||||
"llm_description": "Включить боковую панель чата с ИИ и заметки, созданные на основе больших языковых моделей (LLM)."
|
||||
"disclaimer": "Эти параметры экспериментальные и могут повлиять на стабильность. Используйте с осторожностью."
|
||||
},
|
||||
"popup-editor": {
|
||||
"maximize": "Переключить на полный редактор"
|
||||
@@ -2194,123 +2198,5 @@
|
||||
},
|
||||
"setup_form": {
|
||||
"more_info": "Узнать больше"
|
||||
},
|
||||
"media": {
|
||||
"play": "Воспроизвести (пробел)",
|
||||
"pause": "Пауза (пробел)",
|
||||
"back-10s": "Назад на 10 секунд (стрелка влево)",
|
||||
"forward-30s": "Вперёд на 30 секунд",
|
||||
"mute": "Выключить звук (M)",
|
||||
"unmute": "Включить звук (M)",
|
||||
"playback-speed": "Скорость проигрывания",
|
||||
"loop": "Зациклить",
|
||||
"disable-loop": "Отключить зацикливание",
|
||||
"rotate": "Повернуть",
|
||||
"picture-in-picture": "Картинка в картинке",
|
||||
"exit-picture-in-picture": "Выйти из режима \"картинка в картинке\"",
|
||||
"fullscreen": "Режим полного экрана (F)",
|
||||
"exit-fullscreen": "Выйти из режима полного экрана",
|
||||
"unsupported-format": "Предпросмотр недоступен для данного формата файла:\n{{mime}}",
|
||||
"zoom-to-fit": "Заполнить путём масштабирования",
|
||||
"zoom-reset": "Сбросить заполнение путём масштабирования"
|
||||
},
|
||||
"llm_chat": {
|
||||
"placeholder": "Введите сообщение...",
|
||||
"send": "Отправить",
|
||||
"sending": "Отправка...",
|
||||
"empty_state": "Начните общение, написав сообщение в поле ниже.",
|
||||
"searching_web": "Поиск в сети...",
|
||||
"web_search": "Поиск в сети",
|
||||
"note_tools": "Доступ к заметке",
|
||||
"sources": "Источники",
|
||||
"extended_thinking": "Расширенное мышление",
|
||||
"legacy_models": "Устаревшие модели",
|
||||
"thinking": "Обработка...",
|
||||
"thought_process": "Процесс обработки",
|
||||
"tool_calls": "{{count}} вызов(а/ов) инструмента",
|
||||
"input": "Ввод",
|
||||
"result": "Результат",
|
||||
"error": "Ошибка",
|
||||
"tool_error": "ошибка",
|
||||
"total_tokens": "{{total}} токен(а/ов)",
|
||||
"tokens": "токены",
|
||||
"context_used": "{{percentage}}% использовано",
|
||||
"note_context_enabled": "Нажмите, чтобы отключить контекст заметки: {{title}}",
|
||||
"note_context_disabled": "Нажмите, чтобы включить текущую заметку в контекст",
|
||||
"no_provider_message": "Не выбран провайдер ИИ. Добавьте его для начала общения.",
|
||||
"add_provider": "Добавить провайдера ИИ",
|
||||
"tokens_detail": "{{prompt}} (промт) + {{completion}} (ответ)",
|
||||
"tokens_used": "{{prompt}} (промт) + {{completion}} (ответ) = {{total}} токен(а/ов)",
|
||||
"tokens_used_with_cost": "{{prompt}} (промт) + {{completion}} (ответ) = {{total}} токен(а/ов) (~${{cost}})",
|
||||
"tokens_used_with_model": "{{model}}: {{prompt}} (промт) + {{completion}} (ответ) = {{total}} токен(а/ов)",
|
||||
"tokens_used_with_model_and_cost": "{{model}}: {{prompt}} (промт) + {{completion}} (ответ) = {{total}} токен(а/ов) (~${{cost}})"
|
||||
},
|
||||
"sidebar_chat": {
|
||||
"title": "Чат с ИИ",
|
||||
"launcher_title": "Чат с Open AI",
|
||||
"new_chat": "Начать новый чат",
|
||||
"save_chat": "Сохранить чат в заметках",
|
||||
"empty_state": "Начать общение",
|
||||
"history": "История чата",
|
||||
"recent_chats": "Недавние чаты",
|
||||
"no_chats": "Нет предыдущих чатов"
|
||||
},
|
||||
"mermaid": {
|
||||
"placeholder": "Введите содержимое вашей Mermaid диаграммы или используйте один из примеров ниже.",
|
||||
"sample_diagrams": "Примеры диаграм:",
|
||||
"sample_flowchart": "Блок-схема",
|
||||
"sample_class": "Диаграмма классов",
|
||||
"sample_sequence": "Диаграмма последовательностей",
|
||||
"sample_entity_relationship": "Диаграмма \"Сущность — связь\"",
|
||||
"sample_state": "Диаграмма состояний",
|
||||
"sample_mindmap": "Ментальная карта",
|
||||
"sample_architecture": "Архитектурная схема",
|
||||
"sample_block": "Структурная схема",
|
||||
"sample_gantt": "Диаграмма Ганта",
|
||||
"sample_git": "Git",
|
||||
"sample_kanban": "Канбан",
|
||||
"sample_ishikawa": "Диаграмма Исикавы",
|
||||
"sample_c4": "C4",
|
||||
"sample_packet": "Диаграмма сетевых пакетов",
|
||||
"sample_pie": "Круговая диаграмма",
|
||||
"sample_quadrant": "Квадрантная диаграмма",
|
||||
"sample_radar": "Радиолокационная схема",
|
||||
"sample_requirement": "Диаграмма зависимостей",
|
||||
"sample_sankey": "Диаграмма Сэнки",
|
||||
"sample_timeline": "Временная диаграмма",
|
||||
"sample_treemap": "Древовидная диаграмма",
|
||||
"sample_user_journey": "Карта пользовательского пути",
|
||||
"sample_xy": "XY",
|
||||
"sample_venn": "Диаграмма Венна"
|
||||
},
|
||||
"mind-map": {
|
||||
"addChild": "Добавить дочерний элемент",
|
||||
"addParent": "Добавить родительский элемент",
|
||||
"addSibling": "Добавить элемент на том же уровне",
|
||||
"removeNode": "Удалить узел",
|
||||
"focus": "Режим фокусировки",
|
||||
"cancelFocus": "Отключить режим фокусировки",
|
||||
"moveUp": "Передвинуть выше",
|
||||
"moveDown": "Передвинуть ниже",
|
||||
"link": "Связь",
|
||||
"linkBidirectional": "Двусторонняя связь",
|
||||
"clickTips": "Пожалуйста, нажмите на целевой узел",
|
||||
"summary": "Сводка"
|
||||
},
|
||||
"llm": {
|
||||
"settings_title": "ИИ / LLM",
|
||||
"settings_description": "Настроить интеграции ИИ и больших языковых моделей.",
|
||||
"add_provider": "Добавить провайдера",
|
||||
"add_provider_title": "Добавить провайдера ИИ",
|
||||
"configured_providers": "Настроенные провайдеры",
|
||||
"no_providers_configured": "Ещё нет настроенных провайдеров.",
|
||||
"provider_name": "Название",
|
||||
"provider_type": "Провайдер",
|
||||
"actions": "Действия",
|
||||
"delete_provider": "Удалить",
|
||||
"delete_provider_confirmation": "Вы уверены, что желаете удалить провайдера \"{{name}}\"?",
|
||||
"api_key": "Ключ API",
|
||||
"api_key_placeholder": "Введите ваш ключ API",
|
||||
"cancel": "Отмена"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,6 +76,7 @@
|
||||
"also_delete_note": "Takođe obriši belešku"
|
||||
},
|
||||
"delete_notes": {
|
||||
"delete_notes_preview": "Obriši pregled beleške",
|
||||
"close": "Zatvori",
|
||||
"delete_all_clones_description": "Obriši i sve klonove (može biti poništeno u skorašnjim izmenama)",
|
||||
"erase_notes_description": "Normalno (blago) brisanje samo označava beleške kao obrisane i one mogu biti vraćene (u dijalogu skorašnjih izmena) u određenom vremenskom periodu. Biranje ove opcije će momentalno obrisati beleške i ove beleške neće biti moguće vratiti.",
|
||||
@@ -83,7 +84,9 @@
|
||||
"notes_to_be_deleted": "Sledeće beleške će biti obrisane ({{- noteCount}})",
|
||||
"no_note_to_delete": "Nijedna beleška neće biti obrisana (samo klonovi).",
|
||||
"broken_relations_to_be_deleted": "Sledeći odnosi će biti prekinuti i obrisani ({{- relationCount}})",
|
||||
"cancel": "Otkaži"
|
||||
"cancel": "Otkaži",
|
||||
"ok": "U redu",
|
||||
"deleted_relation_text": "Beleška {{- note}} (za brisanje) je referencirana sa odnosom {{- relation}} koji potiče iz {{- source}}."
|
||||
},
|
||||
"export": {
|
||||
"export_note_title": "Izvezi belešku",
|
||||
|
||||
@@ -21,32 +21,12 @@
|
||||
},
|
||||
"delete_notes": {
|
||||
"close": "Kapat",
|
||||
"delete_notes_preview": "Not önizlemesini sil",
|
||||
"delete_all_clones_description": "Tüm klonları da sil (son değişikliklerden geri alınabilir)",
|
||||
"erase_notes_description": "Normal (yazılımsal) silme işlemi, notları yalnızca silinmiş olarak işaretler ve belirli bir süre içinde (son değişiklikler iletişim kutusunda) geri alınabilir. Bu seçeneği işaretlemek, notları hemen siler ve notların geri alınması mümkün olmaz.",
|
||||
"erase_notes_warning": "Notları, tüm kopyaları da dahil olmak üzere kalıcı olarak silin (geri alınamaz). Bu işlem, uygulamanın yeniden yüklenmesine neden olacaktır.",
|
||||
"notes_to_be_deleted": "Aşağıdaki notlar silinecektir. ({{notesCount}})",
|
||||
"no_note_to_delete": "Hiçbir not silinmeyecek (sadece kopyaları silinecek).",
|
||||
"broken_relations_to_be_deleted": "Aşağıdaki ilişkiler koparılacak ve silinecektir ({{ relationCount}})",
|
||||
"cancel": "İptal"
|
||||
"erase_notes_description": "Normal (yazılımsal) silme işlemi, notları yalnızca silinmiş olarak işaretler ve belirli bir süre içinde (son değişiklikler iletişim kutusunda) geri alınabilir. Bu seçeneği işaretlemek, notları hemen siler ve notların geri alınması mümkün olmaz."
|
||||
},
|
||||
"export": {
|
||||
"close": "Kapat",
|
||||
"export_note_title": "Notu dışa aktar",
|
||||
"export_type_subtree": "Bu not ve tüm torunları",
|
||||
"format_html": "HTML - tüm biçimlendirmeyi koruduğu için önerilir",
|
||||
"format_html_zip": "ZIP arşivindeki HTML dosyaları - tüm biçimlendirmeyi koruduğu için bu yöntem önerilir.",
|
||||
"format_markdown": "Markdown - bu, biçimlendirmenin büyük kısmını korur.",
|
||||
"format_opml": "OPML - yalnızca metin için anahat değişim biçimi. Biçimlendirme, resimler ve dosyalar dahil edilmez.",
|
||||
"opml_version_1": "OPML v1.0 - yalnızca düz metin",
|
||||
"opml_version_2": "OPML v2.0 - HTML de destekler",
|
||||
"export_type_single": "Yalnızca bu not, alt öğeleri olmadan",
|
||||
"export": "Dışa aktar",
|
||||
"choose_export_type": "Lütfen önce dışa aktarma türünü seçin",
|
||||
"export_status": "Dışa aktarma durumu",
|
||||
"export_in_progress": "Dışa aktarma devam ediyor: {{progressCount}}",
|
||||
"export_finished_successfully": "Dışa aktarma başarıyla tamamlandı.",
|
||||
"format_pdf": "PDF - yazdırma veya paylaşım amaçları için.",
|
||||
"share-format": "Web yayını için HTML - paylaşılan notlarda kullanılan temayı kullanır, ancak statik bir web sitesi olarak yayınlanabilir."
|
||||
"close": "Kapat"
|
||||
},
|
||||
"import": {
|
||||
"chooseImportFile": "İçe aktarım dosyası",
|
||||
@@ -78,9 +58,7 @@
|
||||
"widget-render-error": {
|
||||
"title": "Özel React widget'ı çizilirken sorun yaşandı"
|
||||
},
|
||||
"scripting-error": "Kullanıcı tanımlı betik hatası: {{title}}",
|
||||
"widget-missing-parent": "Özel widget'ın zorunlu '{{property}}' özelliği tanımlanmamıştır.\n\nBu komut dosyasının bir kullanıcı arayüzü öğesi olmadan çalıştırılması gerekiyorsa, bunun yerine '#run=frontendStartup' kullanın.",
|
||||
"open-script-note": "Komut dosyası notunu aç"
|
||||
"scripting-error": "Kullanıcı tanımlı betik hatası: {{title}}"
|
||||
},
|
||||
"add_link": {
|
||||
"add_link": "Bağlantı ekle",
|
||||
@@ -125,32 +103,5 @@
|
||||
"are_you_sure_remove_note": "\"{{title}}\" notunu ilişki haritasından kaldırmak istediğinize emin misiniz?. ",
|
||||
"also_delete_note": "Notu da sil",
|
||||
"if_you_dont_check": "Bunu işaretlemezseniz, not yalnızca ilişki haritasından kaldırılacaktır."
|
||||
},
|
||||
"help": {
|
||||
"title": "Özet tablo",
|
||||
"editShortcuts": "Klavye kısayollarını düzenle",
|
||||
"noteNavigation": "Not içinde gezinme",
|
||||
"goUpDown": "Notlar listesinde yukarı/aşağı gitmek",
|
||||
"collapseExpand": "düğümü daralt/genişlet",
|
||||
"notSet": "ayarlanmamış",
|
||||
"goBackForwards": "tarihte geri/ileri git",
|
||||
"showJumpToNoteDialog": "<a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/note-navigation.html#jump-to-note\">\"Şuraya Git\" iletişim kutusunu göster</a>",
|
||||
"scrollToActiveNote": "Aktif nota kaydır",
|
||||
"jumpToParentNote": "Üst nota git",
|
||||
"collapseWholeTree": "Tüm not ağacını daralt",
|
||||
"collapseSubTree": "Alt ağacı daralt",
|
||||
"tabShortcuts": "Sekme kısayolları",
|
||||
"newTabNoteLink": "Not bağlantısı notu yeni sekmede açılır",
|
||||
"newTabWithActivationNoteLink": "Not bağlantısına tıklandığında not yeni bir sekmede açılır ve etkinleştirilir",
|
||||
"onlyInDesktop": "Yalnızca masaüstünde (Electron derlemesi)",
|
||||
"openEmptyTab": "boş sekmeyi aç",
|
||||
"closeActiveTab": "aktif sekmeyi kapat",
|
||||
"activateNextTab": "sonraki sekmeyi etkinleştir",
|
||||
"activatePreviousTab": "önceki sekmeyi etkinleştir",
|
||||
"creatingNotes": "Not oluşturma",
|
||||
"createNoteAfter": "etkin nottan sonra yeni not oluşturma",
|
||||
"createNoteInto": "aktif nota yeni bir alt not oluşturun",
|
||||
"editBranchPrefix": "<a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/tree-concepts.html#prefix\">prefix</a> değerini aktif not klonunun düzenle",
|
||||
"movingCloningNotes": "Notları taşıma / klonlama"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
"also_delete_note": "同時刪除筆記"
|
||||
},
|
||||
"delete_notes": {
|
||||
"delete_notes_preview": "刪除筆記預覽",
|
||||
"delete_all_clones_description": "同時刪除所有克隆(可以在最近修改中撤消)",
|
||||
"erase_notes_description": "通常(軟)刪除僅標記筆記為已刪除,可以在一段時間內透過最近修改對話方塊撤消。勾選此選項將立即擦除筆記,無法撤銷。",
|
||||
"erase_notes_warning": "永久擦除筆記(無法撤銷),包括所有克隆。這將強制應用程式重新載入。",
|
||||
@@ -95,6 +96,8 @@
|
||||
"no_note_to_delete": "沒有筆記將被刪除(僅克隆)。",
|
||||
"broken_relations_to_be_deleted": "將刪除以下關聯並斷開連接 ({{ relationCount}})",
|
||||
"cancel": "取消",
|
||||
"ok": "確定",
|
||||
"deleted_relation_text": "筆記 {{- note}}(將被刪除的筆記)被以下關聯 {{- relation}} 引用,來自 {{- source}}。",
|
||||
"close": "關閉"
|
||||
},
|
||||
"export": {
|
||||
@@ -365,7 +368,7 @@
|
||||
"calendar_root": "標記應用作為每日筆記的根。只應標記一個筆記。",
|
||||
"archived": "含有此標籤的筆記預設在搜尋結果中不可見(也適用於跳轉至、新增連結對話方塊等)。",
|
||||
"exclude_from_export": "筆記(及其子階層)不會包含在任何匯出的筆記中",
|
||||
"run": "定義腳本應運行的事件。可能的值包括:\n<ul>\n<li>frontendStartup - Trilium前端啟動時(或重新整理時),但不會在移動端執行。</li>\n<li>mobileStartup - Trilium前端啟動時(或重新整理時), 在行動端會執行。</li>\n<li>backendStartup - Trilium後端啟動時。</li>\n<li>hourly - 每小時運行一次。您可以使用附加標籤<code>runAtHour</code>指定小時。</li>\n<li>daily - 每天運行一次。</li>\n</ul>",
|
||||
"run": "定義腳本應運行的事件。可能的值包括:\n<ul>\n<li>frontendStartup - Trilium前端啟動時(或重新整理時),但不會在移動端執行。</li>\n<li>mobileStartup - Trilium前端啟動時(或重新整理時), 在行動端會執行。</li>\n<li>backendStartup - Trilium後端啟動時</li>\n<li>hourly - 每小時運行一次。您可以使用附加標籤<code>runAtHour</code>指定小時。</li>\n<li>daily - 每天運行一次</li>\n</ul>",
|
||||
"run_on_instance": "定義應在哪個 Trilium 實例上運行。預設為所有實例。",
|
||||
"run_at_hour": "應在哪個小時運行。應與<code>#run=hourly</code>一起使用。可以多次定義,以便一天內運行多次。",
|
||||
"disable_inclusion": "含有此標籤的腳本不會包含在父腳本執行中。",
|
||||
@@ -443,8 +446,7 @@
|
||||
"app_theme_base": "設定為 \"next\"、\"next-light \" 或 \"next-dark\",以使用相應的 TriliumNext 主題(自動、淺色或深色)作為自訂主題的基礎,而非傳統主題。",
|
||||
"print_landscape": "匯出為 PDF 時,將頁面方向更改為橫向而非縱向。",
|
||||
"print_page_size": "在匯出 PDF 時更改頁面大小。支援的值:<code>A0</code>、<code>A1</code>、<code>A2</code>、<code>A3</code>、<code>A4</code>、<code>A5</code>、<code>A6</code>、<code>Legal</code>、<code>Letter</code>、<code>Tabloid</code>、<code>Ledger</code>。",
|
||||
"color_type": "顏色",
|
||||
"textarea": "多行文字"
|
||||
"color_type": "顏色"
|
||||
},
|
||||
"attribute_editor": {
|
||||
"help_text_body1": "要新增標籤,只需輸入例如 <code>#rock</code> 或者如果您還想新增值,則例如 <code>#year = 2020</code>",
|
||||
@@ -703,8 +705,7 @@
|
||||
"export_as_image": "匯出為圖片",
|
||||
"export_as_image_png": "PNG (點陣)",
|
||||
"export_as_image_svg": "SVG (向量)",
|
||||
"note_map": "筆記地圖",
|
||||
"view_ocr_text": "顯示 OCR 文字"
|
||||
"note_map": "筆記地圖"
|
||||
},
|
||||
"onclick_button": {
|
||||
"no_click_handler": "按鈕元件'{{componentId}}'沒有定義點擊時的處理方式"
|
||||
@@ -800,10 +801,7 @@
|
||||
"expand_first_level": "展開直接子級",
|
||||
"expand_nth_level": "展開 {{depth}} 層",
|
||||
"expand_all_levels": "展開所有層級",
|
||||
"hide_child_notes": "隱藏樹中的子筆記",
|
||||
"open_all_in_tabs": "全部打開",
|
||||
"open_all_in_tabs_tooltip": "在新分頁中開啟所有結果",
|
||||
"open_all_confirm": "這將在新分頁中開啟 {{count}} 則筆記。要繼續嗎?"
|
||||
"hide_child_notes": "隱藏樹中的子筆記"
|
||||
},
|
||||
"edited_notes": {
|
||||
"no_edited_notes_found": "今天還沒有編輯過的筆記...",
|
||||
@@ -857,8 +855,7 @@
|
||||
"collapse": "收摺到正常大小",
|
||||
"title": "筆記地圖",
|
||||
"fix-nodes": "固定節點",
|
||||
"link-distance": "連結距離",
|
||||
"too-many-notes": "此子樹包含 {{count}} 則筆記,已超過筆記地圖中可顯示的 {{max}} 則上限。"
|
||||
"link-distance": "連結距離"
|
||||
},
|
||||
"note_paths": {
|
||||
"title": "筆記路徑",
|
||||
@@ -1049,6 +1046,7 @@
|
||||
"unprotecting-title": "解除保護狀態"
|
||||
},
|
||||
"relation_map": {
|
||||
"open_in_new_tab": "在新分頁中打開",
|
||||
"remove_note": "刪除筆記",
|
||||
"edit_title": "編輯標題",
|
||||
"rename_note": "重新命名筆記",
|
||||
@@ -1063,8 +1061,7 @@
|
||||
"note_already_in_diagram": "筆記 \"{{title}}\" 已經在圖中。",
|
||||
"enter_title_of_new_note": "輸入新筆記的標題",
|
||||
"default_new_note_title": "新筆記",
|
||||
"click_on_canvas_to_place_new_note": "點擊畫布以放置新筆記",
|
||||
"rename_relation": "重新命名關聯"
|
||||
"click_on_canvas_to_place_new_note": "點擊畫布以放置新筆記"
|
||||
},
|
||||
"backend_log": {
|
||||
"refresh": "重新整理"
|
||||
@@ -1199,28 +1196,12 @@
|
||||
},
|
||||
"images": {
|
||||
"images_section_title": "圖片",
|
||||
"download_images_automatically": "自動下載圖片",
|
||||
"download_images_description": "從貼上的 HTML 下載引用的線上圖片以便離線使用。",
|
||||
"enable_image_compression": "圖片壓縮",
|
||||
"max_image_dimensions": "最大圖片尺寸",
|
||||
"jpeg_quality_description": "建議範圍為 50–85。較低的數值可縮小檔案大小,較高的數值則能保留更多細節。",
|
||||
"max_image_dimensions_unit": "像素",
|
||||
"enable_image_compression_description": "在上傳或貼上圖片時壓縮並調整圖片大小。",
|
||||
"max_image_dimensions_description": "超過此尺寸的圖片將會自動調整大小。",
|
||||
"jpeg_quality": "JPEG 品質",
|
||||
"ocr_section_title": "文字擷取(OCR)",
|
||||
"ocr_related_content_languages": "內容語言(用於文字擷取)",
|
||||
"ocr_auto_process": "自動處理新檔案",
|
||||
"ocr_auto_process_description": "自動從新上傳或貼上的檔案中擷取文字。",
|
||||
"ocr_min_confidence": "最低信賴度",
|
||||
"ocr_confidence_description": "僅提取高於此信賴度閾值的文字。較低的閾值雖能包含更多文字,但準確度可能較低。",
|
||||
"batch_ocr_title": "處理現有檔案",
|
||||
"batch_ocr_description": "從筆記中的所有現有圖片、PDF 檔案及 Office 文件中擷取文字。根據檔案數量多寡,此過程可能需要一些時間。",
|
||||
"batch_ocr_start": "開始批次處理",
|
||||
"batch_ocr_starting": "開始批次處理…",
|
||||
"batch_ocr_progress": "正在處理 {{processed}} 個檔案,共 {{total}} 個檔案…",
|
||||
"batch_ocr_completed": "批次處理完成!已處理 {{processed}} 個檔案。",
|
||||
"batch_ocr_error": "批次處理期間發生錯誤:{{error}}"
|
||||
"download_images_automatically": "自動下載圖片以供離線使用。",
|
||||
"download_images_description": "貼上的 HTML 可能包含線上圖片的引用,Trilium 會找到這些引用並下載圖片,以便它們可以離線使用。",
|
||||
"enable_image_compression": "啟用圖片壓縮",
|
||||
"max_image_dimensions": "圖片的最大寬度 / 高度(超過此限制的圖片將會被縮放)。",
|
||||
"jpeg_quality_description": "JPEG 質量(10 - 最差質量,100 最佳質量,建議為 50 - 85)",
|
||||
"max_image_dimensions_unit": "像素"
|
||||
},
|
||||
"attachment_erasure_timeout": {
|
||||
"attachment_erasure_timeout": "附件清理超時",
|
||||
@@ -1333,8 +1314,7 @@
|
||||
"date-and-time": "日期和時間",
|
||||
"path": "路徑",
|
||||
"database_backed_up_to": "資料庫已備份至 {{backupFilePath}}",
|
||||
"no_backup_yet": "尚無備份",
|
||||
"download": "下載"
|
||||
"no_backup_yet": "尚無備份"
|
||||
},
|
||||
"etapi": {
|
||||
"title": "ETAPI",
|
||||
@@ -1399,15 +1379,12 @@
|
||||
"spellcheck": {
|
||||
"title": "拼寫檢查",
|
||||
"description": "這些選項僅適用於桌面版,瀏覽器將使用其原生的拼寫檢查功能。",
|
||||
"enable": "拼寫檢查",
|
||||
"language_code_label": "拼寫檢查語言",
|
||||
"restart-required": "拼寫檢查選項的更改將在應用重啟後生效。",
|
||||
"custom_dictionary_title": "自訂字典",
|
||||
"custom_dictionary_description": "新增至字典的詞彙會同步至您所有的裝置。",
|
||||
"custom_dictionary_edit": "自訂詞彙",
|
||||
"custom_dictionary_edit_description": "編輯拼寫檢查器不應標記的詞彙清單。變更將於重新啟動後生效。",
|
||||
"custom_dictionary_open": "編輯字典",
|
||||
"related_description": "設定拼寫檢查語言及自訂字典。"
|
||||
"enable": "啟用拼寫檢查",
|
||||
"language_code_label": "語言代碼",
|
||||
"language_code_placeholder": "例如 \"en-US\", \"de-AT\"",
|
||||
"multiple_languages_info": "多種語言可以用逗號分隔,例如 \"en-US, de-DE, cs\"。 ",
|
||||
"available_language_codes_label": "可用的語言代碼:",
|
||||
"restart-required": "拼寫檢查選項的更改將在應用重啟後生效。"
|
||||
},
|
||||
"sync_2": {
|
||||
"config_title": "同步設定",
|
||||
@@ -1423,7 +1400,7 @@
|
||||
"test_description": "測試和同步伺服器之間的連接。如果同步伺服器沒有初始化,這會將本地文件同步至同步伺服器上。",
|
||||
"test_button": "測試同步",
|
||||
"handshake_failed": "同步伺服器握手失敗,錯誤:{{message}}",
|
||||
"timeout_description": "在放棄慢速同步連線前應等待多久。若網路不穩定,請延長等待時間。"
|
||||
"timeout_unit": "毫秒"
|
||||
},
|
||||
"api_log": {
|
||||
"close": "關閉"
|
||||
@@ -1520,8 +1497,7 @@
|
||||
"new-feature": "新增",
|
||||
"collections": "集合",
|
||||
"ai-chat": "AI 聊天",
|
||||
"spreadsheet": "試算表",
|
||||
"llm-chat": "AI 對話"
|
||||
"spreadsheet": "試算表"
|
||||
},
|
||||
"protect_note": {
|
||||
"toggle-on": "保護筆記",
|
||||
@@ -1890,7 +1866,7 @@
|
||||
},
|
||||
"content_language": {
|
||||
"title": "內文語言",
|
||||
"description": "選擇一種或多種語言作為唯讀或可編輯文字筆記的可選基本屬性,這將支援拼寫檢查、從右向左及文字擷取 (OCR) 等功能。"
|
||||
"description": "選擇一種或多種語言作為唯讀或可編輯文字筆記的可選基本屬性,這將支援拼寫檢查或從右向左之類的功能。"
|
||||
},
|
||||
"switch_layout_button": {
|
||||
"title_vertical": "將編輯面板移至底部",
|
||||
@@ -2070,9 +2046,7 @@
|
||||
"title": "實驗性選項",
|
||||
"disclaimer": "這些選項屬實驗性質,可能導致系統不穩定。請謹慎使用。",
|
||||
"new_layout_name": "新版面配置",
|
||||
"new_layout_description": "體驗全新版面配置,呈現更現代的外觀與更佳的使用體驗。在未來版本將進行大幅調整。",
|
||||
"llm_name": "AI / LLM 對話",
|
||||
"llm_description": "啟用由大語言模型驅動的 AI 聊天側邊欄及 LLM 聊天筆記。"
|
||||
"new_layout_description": "體驗全新版面配置,呈現更現代的外觀與更佳的使用體驗。在未來版本將進行大幅調整。"
|
||||
},
|
||||
"server": {
|
||||
"unknown_http_error_title": "與伺服器通訊錯誤",
|
||||
@@ -2209,167 +2183,5 @@
|
||||
},
|
||||
"setup_form": {
|
||||
"more_info": "了解更多"
|
||||
},
|
||||
"media": {
|
||||
"play": "播放 (空白鍵)",
|
||||
"pause": "暫停 (空白鍵)",
|
||||
"back-10s": "往前 10 秒 (左方向鍵)",
|
||||
"forward-30s": "往後 30 秒",
|
||||
"mute": "靜音 (M)",
|
||||
"unmute": "解除靜音 (M)",
|
||||
"playback-speed": "播放速度",
|
||||
"loop": "循環",
|
||||
"disable-loop": "解除循環",
|
||||
"rotate": "旋轉",
|
||||
"picture-in-picture": "畫中畫",
|
||||
"exit-picture-in-picture": "退出畫中畫",
|
||||
"fullscreen": "全螢幕 (F)",
|
||||
"exit-fullscreen": "退出全螢幕",
|
||||
"unsupported-format": "此檔案格式不支援媒體預覽:\n{{mime}}",
|
||||
"zoom-to-fit": "放大至填滿畫面",
|
||||
"zoom-reset": "重設放大至填滿畫面"
|
||||
},
|
||||
"mermaid": {
|
||||
"placeholder": "請輸入您的美人魚圖表內容,或選用下方其中一個範例圖表。",
|
||||
"sample_diagrams": "範例圖表:",
|
||||
"sample_flowchart": "流程圖",
|
||||
"sample_class": "階層圖",
|
||||
"sample_sequence": "時序圖",
|
||||
"sample_entity_relationship": "實體關係圖",
|
||||
"sample_state": "狀態圖",
|
||||
"sample_mindmap": "心智圖",
|
||||
"sample_architecture": "架構圖",
|
||||
"sample_block": "區塊圖",
|
||||
"sample_c4": "C4 圖",
|
||||
"sample_gantt": "甘特圖",
|
||||
"sample_git": "Git 分支圖",
|
||||
"sample_kanban": "看板圖",
|
||||
"sample_packet": "數據包圖",
|
||||
"sample_pie": "圓餅圖",
|
||||
"sample_quadrant": "象限圖",
|
||||
"sample_radar": "雷達圖",
|
||||
"sample_requirement": "需求圖",
|
||||
"sample_sankey": "桑基圖",
|
||||
"sample_timeline": "時間軸",
|
||||
"sample_treemap": "樹狀圖",
|
||||
"sample_user_journey": "使用者旅程",
|
||||
"sample_xy": "XY 圖表",
|
||||
"sample_venn": "韋恩圖",
|
||||
"sample_ishikawa": "魚骨圖",
|
||||
"sample_treeview": "樹狀視圖",
|
||||
"sample_wardley": "沃德利地圖"
|
||||
},
|
||||
"llm_chat": {
|
||||
"placeholder": "輸入訊息…",
|
||||
"send": "送出",
|
||||
"sending": "正在送出…",
|
||||
"empty_state": "請在下方輸入訊息,開啟對話。",
|
||||
"searching_web": "正在搜尋網頁…",
|
||||
"web_search": "網頁搜尋",
|
||||
"note_tools": "筆記存取",
|
||||
"sources": "來源",
|
||||
"sources_summary": "來自 {{sites}} 個網站的 {{count}} 個來源",
|
||||
"extended_thinking": "延伸思考",
|
||||
"legacy_models": "傳統模型",
|
||||
"thinking": "正在思考…",
|
||||
"thought_process": "思考過程",
|
||||
"tool_calls": "{{count}} 次工具調用",
|
||||
"input": "輸入",
|
||||
"result": "結果",
|
||||
"error": "錯誤",
|
||||
"tool_error": "失敗",
|
||||
"total_tokens": "{{total}} 個詞元",
|
||||
"tokens_detail": "{{prompt}} 提示詞 + {{completion}} 補全",
|
||||
"tokens_used": "{{prompt}} 提示詞 + {{completion}} 補全 = {{total}} 個詞元",
|
||||
"tokens_used_with_cost": "{{prompt}} 提示詞 + {{completion}} 補全 = {{total}} 個詞元(約 ${{cost}})",
|
||||
"tokens_used_with_model": "{{model}}:{{prompt}} 提示詞 + {{completion}} 補全 = {{total}} 個詞元",
|
||||
"tokens_used_with_model_and_cost": "{{model}}:{{prompt}} 提示詞 + {{completion}} 補全 = {{total}} 個詞元(約 ${{cost}})",
|
||||
"tokens": "詞元",
|
||||
"context_used": "已使用 {{percentage}}%",
|
||||
"note_context_enabled": "點擊以禁用筆記上下文:{{title}}",
|
||||
"note_context_disabled": "點擊將當前筆記納入上下文",
|
||||
"no_provider_message": "尚未設定任何 AI 服務提供者。請新增一個以開始聊天。",
|
||||
"add_provider": "新增 AI 提供者"
|
||||
},
|
||||
"ocr": {
|
||||
"processing_complete": "OCR 處理已完成。",
|
||||
"processing_failed": "無法啟動 OCR 處理",
|
||||
"text_filtered_low_confidence": "OCR 偵測到的文字信賴度為 {{confidence}}%,但因您的最低閾值設定為 {{threshold}}%,故該結果已被捨棄。",
|
||||
"open_media_settings": "開啟設定",
|
||||
"view_extracted_text": "檢視擷取的文字 (OCR)",
|
||||
"extracted_text": "已擷取的文字 (OCR)",
|
||||
"extracted_text_title": "已擷取的文字 (OCR)",
|
||||
"loading_text": "正在載入 OCR 文字…",
|
||||
"no_text_available": "無 OCR 文字可用",
|
||||
"no_text_explanation": "此筆記尚未經過 OCR 文字擷取處理,或未找到任何文字。",
|
||||
"failed_to_load": "載入 OCR 文字失敗",
|
||||
"process_now": "處理 OCR",
|
||||
"processing": "正在處理…",
|
||||
"processing_started": "OCR 處理已開始。請稍候片刻並重新整理頁面。"
|
||||
},
|
||||
"mind-map": {
|
||||
"addChild": "新增子節點",
|
||||
"addParent": "新增父節點",
|
||||
"addSibling": "新增同級節點",
|
||||
"removeNode": "刪除節點",
|
||||
"focus": "專注模式",
|
||||
"cancelFocus": "退出專注模式",
|
||||
"moveUp": "上移",
|
||||
"moveDown": "下移",
|
||||
"link": "連結",
|
||||
"linkBidirectional": "雙向連結",
|
||||
"clickTips": "請點擊目標節點",
|
||||
"summary": "摘要"
|
||||
},
|
||||
"llm": {
|
||||
"settings_title": "AI / LLM",
|
||||
"settings_description": "設定 AI 及大型語言模型整合。",
|
||||
"feature_not_enabled": "請前往「設定」→「進階」→「實驗性功能」啟用 LLM 實驗性功能,即可使用 AI 整合。",
|
||||
"add_provider": "新增提供者",
|
||||
"add_provider_title": "新增 AI 提供者",
|
||||
"configured_providers": "已設定的提供者",
|
||||
"no_providers_configured": "尚未設定任何提供者。",
|
||||
"provider_name": "名稱",
|
||||
"provider_type": "提供者",
|
||||
"actions": "動作",
|
||||
"delete_provider": "刪除",
|
||||
"delete_provider_confirmation": "您確定要刪除提供者 \"{{name}}\" 嗎?",
|
||||
"api_key": "API 金鑰",
|
||||
"api_key_placeholder": "請輸入您的 API 金鑰",
|
||||
"cancel": "取消",
|
||||
"mcp_title": "MCP(模型上下文協定)",
|
||||
"mcp_enabled": "MCP 伺服器",
|
||||
"mcp_enabled_description": "公開一個模型上下文協定 (MCP) 端點,以便人工智慧編程助手(例如 Claude Code、GitHub Copilot)能夠讀取並修改您的筆記。此端點僅限從 localhost 存取。",
|
||||
"mcp_endpoint_title": "端點網址",
|
||||
"mcp_endpoint_description": "將此網址新增至您的 AI 助理的 MCP 設定中",
|
||||
"tools": {
|
||||
"search_notes": "搜尋筆記",
|
||||
"get_note": "取得筆記",
|
||||
"get_note_content": "取得筆記內容",
|
||||
"update_note_content": "更新筆記內容",
|
||||
"append_to_note": "追加至筆記",
|
||||
"create_note": "建立筆記",
|
||||
"get_attributes": "取得屬性",
|
||||
"get_attribute": "取得屬性",
|
||||
"set_attribute": "設定屬性",
|
||||
"delete_attribute": "移除屬性",
|
||||
"get_child_notes": "取得子筆記",
|
||||
"get_subtree": "取得子階層",
|
||||
"load_skill": "載入技能",
|
||||
"web_search": "網頁搜尋",
|
||||
"note_in_parent": "<Note/> 於 <Parent/>",
|
||||
"get_attachment": "取得附件",
|
||||
"get_attachment_content": "讀取附件內容"
|
||||
}
|
||||
},
|
||||
"sidebar_chat": {
|
||||
"title": "AI 對話",
|
||||
"launcher_title": "打開 AI 對話",
|
||||
"new_chat": "開始新對話",
|
||||
"save_chat": "將對話保存至筆記",
|
||||
"empty_state": "開始會話",
|
||||
"history": "對話歷史",
|
||||
"recent_chats": "最近的對話",
|
||||
"no_chats": "無先前的對話記錄"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,6 +186,7 @@
|
||||
"also_delete_note": "Також видалити нотатку"
|
||||
},
|
||||
"delete_notes": {
|
||||
"delete_notes_preview": "Видалити попередній перегляд нотаток",
|
||||
"close": "Закрити",
|
||||
"delete_all_clones_description": "Видалити також усі клони (можна скасувати в останніх змінах)",
|
||||
"erase_notes_description": "Звичайне (м’яке) видалення лише позначає нотатки як видалені і їх можна відновити (у діалоговому вікні останніх змін) протягом певного періоду часу. Якщо позначити цю опцію, нотатки будуть видалені негайно і їх неможливо буде відновити.",
|
||||
@@ -193,7 +194,9 @@
|
||||
"notes_to_be_deleted": "Наступні нотатки будуть видалені ({{notesCount}})",
|
||||
"no_note_to_delete": "Жодну нотатку не буде видалено (лише клони).",
|
||||
"broken_relations_to_be_deleted": "Наступні зв'язки будуть розірвані та видалені ({{ relationCount}})",
|
||||
"cancel": "Скасувати"
|
||||
"cancel": "Скасувати",
|
||||
"ok": "ОК",
|
||||
"deleted_relation_text": "Нотатка {{- note}} (буде видалена) посилається на зв'язок {{- relation}}, що походить з {{- source}}."
|
||||
},
|
||||
"export": {
|
||||
"export_note_title": "Експорт нотатки",
|
||||
@@ -1148,6 +1151,7 @@
|
||||
"unprotecting-title": "Статус зняття захисту"
|
||||
},
|
||||
"relation_map": {
|
||||
"open_in_new_tab": "Відкрити в новій вкладці",
|
||||
"remove_note": "Видалити нотатку",
|
||||
"edit_title": "Редагувати заголовок",
|
||||
"rename_note": "Перейменувати нотатку",
|
||||
@@ -1741,12 +1745,16 @@
|
||||
"description": "Ці параметри застосовуються лише для збірок для ПК, браузери використовуватимуть власну вбудовану перевірку орфографії.",
|
||||
"enable": "Увімкнути перевірку орфографії",
|
||||
"language_code_label": "Код(и) мови",
|
||||
"language_code_placeholder": "наприклад, \"en-US\", \"de-AT\"",
|
||||
"multiple_languages_info": "Кілька мов можна розділяти комами, наприклад, \"en-US, de-DE, cs\". ",
|
||||
"available_language_codes_label": "Доступні коди мови:",
|
||||
"restart-required": "Зміни в параметрах перевірки орфографії набудуть чинності після перезапуску програми."
|
||||
},
|
||||
"sync_2": {
|
||||
"config_title": "Конфігурація синхронізації",
|
||||
"server_address": "Адреса екземпляра сервера",
|
||||
"timeout": "Тайм-аут синхронізації",
|
||||
"timeout_unit": "мілісекунди",
|
||||
"proxy_label": "Синхронізація проксі-сервера (необов'язково)",
|
||||
"note": "Нотатка",
|
||||
"note_description": "Якщо залишити налаштування проксі-сервера порожнім, буде використано системний проксі-сервер (стосується лише збірки для ПК/електронної версії).",
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
},
|
||||
"delete_notes": {
|
||||
"close": "Đóng",
|
||||
"ok": "OK",
|
||||
"cancel": "Huỷ"
|
||||
},
|
||||
"export": {
|
||||
|
||||
1
apps/client/src/types-lib.d.ts
vendored
1
apps/client/src/types-lib.d.ts
vendored
@@ -66,7 +66,6 @@ declare module "preact" {
|
||||
interface ElectronWebViewElement extends JSX.HTMLAttributes<HTMLElement> {
|
||||
src: string;
|
||||
class: string;
|
||||
key?: string | number;
|
||||
}
|
||||
|
||||
interface IntrinsicElements {
|
||||
|
||||
6
apps/client/src/types.d.ts
vendored
6
apps/client/src/types.d.ts
vendored
@@ -24,7 +24,6 @@ interface CustomGlobals {
|
||||
getReferenceLinkTitle: (href: string) => Promise<string>;
|
||||
getReferenceLinkTitleSync: (href: string) => string;
|
||||
getActiveContextNote: () => FNote | null;
|
||||
getThemeStyle: () => "auto" | "light" | "dark";
|
||||
ESLINT: Library;
|
||||
appContext: AppContext;
|
||||
froca: Froca;
|
||||
@@ -52,9 +51,8 @@ interface CustomGlobals {
|
||||
isElectron: boolean;
|
||||
isRtl: boolean;
|
||||
iconRegistry: IconRegistry;
|
||||
theme: string;
|
||||
themeBase?: "next" | "next-light" | "next-dark";
|
||||
customThemeCssUrl?: string;
|
||||
themeCssUrl: string;
|
||||
themeUseNextAsBase?: "next" | "next-light" | "next-dark";
|
||||
iconPackCss: string;
|
||||
headingStyle: "plain" | "underline" | "markdown";
|
||||
layoutOrientation: "vertical" | "horizontal";
|
||||
|
||||
@@ -336,8 +336,6 @@ export async function getExtendedWidgetType(note: FNote | null | undefined, note
|
||||
|
||||
if (noteContext?.viewScope?.viewMode === "source") {
|
||||
resultingType = "readOnlyCode";
|
||||
} else if (noteContext.viewScope?.viewMode === "ocr") {
|
||||
resultingType = "readOnlyOCRText";
|
||||
} else if (noteContext.viewScope?.viewMode === "attachments") {
|
||||
resultingType = noteContext.viewScope.attachmentId ? "attachmentDetail" : "attachmentList";
|
||||
} else if (noteContext.viewScope?.viewMode === "note-map") {
|
||||
|
||||
@@ -2,7 +2,7 @@ import "./PromotedAttributes.css";
|
||||
|
||||
import { UpdateAttributeResponse } from "@triliumnext/commons";
|
||||
import clsx from "clsx";
|
||||
import { ComponentChild, createElement, HTMLInputTypeAttribute, InputHTMLAttributes, MouseEventHandler, TargetedEvent, TargetedInputEvent } from "preact";
|
||||
import { ComponentChild, HTMLInputTypeAttribute, InputHTMLAttributes, MouseEventHandler, TargetedEvent, TargetedInputEvent } from "preact";
|
||||
import { Dispatch, StateUpdater, useCallback, useEffect, useRef, useState } from "preact/hooks";
|
||||
|
||||
import NoteContext from "../components/note_context";
|
||||
@@ -36,7 +36,7 @@ interface CellProps {
|
||||
setCellToFocus(cell: Cell): void;
|
||||
}
|
||||
|
||||
type OnChangeEventData = TargetedEvent<HTMLInputElement | HTMLTextAreaElement, Event> | InputEvent | JQuery.TriggeredEvent<HTMLInputElement, undefined, HTMLInputElement, HTMLInputElement>;
|
||||
type OnChangeEventData = TargetedEvent<HTMLInputElement, Event> | InputEvent | JQuery.TriggeredEvent<HTMLInputElement, undefined, HTMLInputElement, HTMLInputElement>;
|
||||
type OnChangeListener = (e: OnChangeEventData) => void | Promise<void>;
|
||||
|
||||
export default function PromotedAttributes() {
|
||||
@@ -171,9 +171,8 @@ function PromotedAttributeCell(props: CellProps) {
|
||||
);
|
||||
}
|
||||
|
||||
const LABEL_MAPPINGS: Record<LabelType, HTMLInputTypeAttribute | undefined> = {
|
||||
const LABEL_MAPPINGS: Record<LabelType, HTMLInputTypeAttribute> = {
|
||||
text: "text",
|
||||
textarea: undefined,
|
||||
number: "number",
|
||||
boolean: "checkbox",
|
||||
date: "date",
|
||||
@@ -227,21 +226,20 @@ function LabelInput(props: CellProps & { inputId: string }) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const inputNode = createElement(definition.labelType === "textarea" ? "textarea" : "input", {
|
||||
className: "form-control promoted-attribute-input",
|
||||
tabIndex: 200 + definitionAttr.position,
|
||||
id: inputId,
|
||||
type: LABEL_MAPPINGS[definition.labelType ?? "text"],
|
||||
value: valueDraft,
|
||||
checked: definition.labelType === "boolean" ? valueAttr.value === "true" : undefined,
|
||||
placeholder: t("promoted_attributes.unset-field-placeholder"),
|
||||
"data-attribute-id": valueAttr.attributeId,
|
||||
"data-attribute-type": valueAttr.type,
|
||||
"data-attribute-name": valueAttr.name,
|
||||
onBlur: onChangeListener,
|
||||
...extraInputProps
|
||||
});
|
||||
const inputNode = <input
|
||||
className="form-control promoted-attribute-input"
|
||||
tabIndex={200 + definitionAttr.position}
|
||||
id={inputId}
|
||||
type={LABEL_MAPPINGS[definition.labelType ?? "text"]}
|
||||
value={valueDraft}
|
||||
checked={definition.labelType === "boolean" ? valueAttr.value === "true" : undefined}
|
||||
placeholder={t("promoted_attributes.unset-field-placeholder")}
|
||||
data-attribute-id={valueAttr.attributeId}
|
||||
data-attribute-type={valueAttr.type}
|
||||
data-attribute-name={valueAttr.name}
|
||||
onBlur={onChangeListener}
|
||||
{...extraInputProps}
|
||||
/>;
|
||||
|
||||
if (definition.labelType === "boolean") {
|
||||
return <>
|
||||
|
||||
@@ -28,10 +28,9 @@
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.toast.no-title .toast-main-row {
|
||||
.toast.no-title {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.toast.no-title .toast-icon {
|
||||
@@ -41,26 +40,22 @@
|
||||
}
|
||||
|
||||
.toast.no-title .toast-body {
|
||||
flex: 1;
|
||||
padding-block: var(--bs-toast-padding-y);
|
||||
padding-inline: 0;
|
||||
padding-inline-start: 0;
|
||||
padding-inline-end: 0;
|
||||
}
|
||||
|
||||
.toast.no-title .toast-close {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: var(--bs-toast-padding-y) var(--bs-toast-padding-x);
|
||||
.toast.no-title .toast-header {
|
||||
background-color: unset !important;
|
||||
}
|
||||
|
||||
.toast {
|
||||
.toast-buttons {
|
||||
padding: 0 var(--bs-toast-padding-x) var(--bs-toast-padding-y) var(--bs-toast-padding-x);
|
||||
padding: 0 1em 1em 1em;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5em;
|
||||
gap: 1em;
|
||||
justify-content: space-between;
|
||||
|
||||
.btn {
|
||||
width: 100%;
|
||||
color: var(--bs-toast-color);
|
||||
background: var(--modal-control-button-background);
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useEffect } from "preact/hooks";
|
||||
|
||||
import { removeToastFromStore, ToastOptionsWithRequiredId, toasts } from "../services/toast";
|
||||
import Icon from "./react/Icon";
|
||||
import { RawHtmlBlock } from "./react/RawHtml";
|
||||
import Button from "./react/Button";
|
||||
|
||||
export default function ToastContainer() {
|
||||
@@ -42,24 +43,21 @@ function Toast({ id, title, timeout, progress, message, icon, buttons }: ToastOp
|
||||
id={`toast-${id}`}
|
||||
>
|
||||
{title ? (
|
||||
<>
|
||||
<div class="toast-header">
|
||||
<strong class="me-auto">
|
||||
{toastIcon}
|
||||
<span class="toast-title">{title}</span>
|
||||
</strong>
|
||||
{closeButton}
|
||||
</div>
|
||||
<div className="toast-body">{message}</div>
|
||||
</>
|
||||
) : (
|
||||
<div class="toast-main-row">
|
||||
<div class="toast-icon">{toastIcon}</div>
|
||||
<div className="toast-body">{message}</div>
|
||||
<div class="toast-close">{closeButton}</div>
|
||||
<div class="toast-header">
|
||||
<strong class="me-auto">
|
||||
{toastIcon}
|
||||
<span class="toast-title">{title}</span>
|
||||
</strong>
|
||||
{closeButton}
|
||||
</div>
|
||||
) : (
|
||||
<div class="toast-icon">{toastIcon}</div>
|
||||
)}
|
||||
|
||||
<RawHtmlBlock className="toast-body" html={message} />
|
||||
|
||||
{!title && <div class="toast-header">{closeButton}</div>}
|
||||
|
||||
{buttons && (
|
||||
<div class="toast-buttons">
|
||||
{buttons.map(({ text, onClick }) => (
|
||||
|
||||
@@ -87,7 +87,7 @@ function buildUserAttribute(attr: AttributeWithDefinitions): ComponentChildren {
|
||||
content = <><Icon icon={value === "true" ? "bx bx-check-square" : "bx bx-square"} />{" "}<strong>{attr.friendlyName}</strong></>;
|
||||
break;
|
||||
case "url":
|
||||
content = <a href={value} target="_blank" rel="noopener noreferrer" onClick={(e) => e.stopPropagation()}>{attr.friendlyName}</a>;
|
||||
content = <a href={value} target="_blank" rel="noopener noreferrer">{attr.friendlyName}</a>;
|
||||
break;
|
||||
case "color":
|
||||
style = { backgroundColor: value, color: getReadableTextColor(value) };
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import appContext from "../../components/app_context.js";
|
||||
import attributeAutocompleteService from "../../services/attribute_autocomplete.js";
|
||||
import type { Attribute } from "../../services/attribute_parser.js";
|
||||
import { isExperimentalFeatureEnabled } from "../../services/experimental_features.js";
|
||||
import { focusSavedElement, saveFocusedElement } from "../../services/focus.js";
|
||||
import froca from "../../services/froca.js";
|
||||
import { t } from "../../services/i18n.js";
|
||||
import server from "../../services/server.js";
|
||||
import froca from "../../services/froca.js";
|
||||
import linkService from "../../services/link.js";
|
||||
import attributeAutocompleteService from "../../services/attribute_autocomplete.js";
|
||||
import noteAutocompleteService from "../../services/note_autocomplete.js";
|
||||
import promotedAttributeDefinitionParser from "../../services/promoted_attribute_definition_parser.js";
|
||||
import server from "../../services/server.js";
|
||||
import shortcutService from "../../services/shortcuts.js";
|
||||
import NoteContextAwareWidget from "../note_context_aware_widget.js";
|
||||
import SpacedUpdate from "../../services/spaced_update.js";
|
||||
import utils from "../../services/utils.js";
|
||||
import NoteContextAwareWidget from "../note_context_aware_widget.js";
|
||||
import shortcutService from "../../services/shortcuts.js";
|
||||
import appContext from "../../components/app_context.js";
|
||||
import type { Attribute } from "../../services/attribute_parser.js";
|
||||
import { focusSavedElement, saveFocusedElement } from "../../services/focus.js";
|
||||
import { isExperimentalFeatureEnabled } from "../../services/experimental_features.js";
|
||||
|
||||
const TPL = /*html*/`
|
||||
<div class="attr-detail tn-tool-dialog">
|
||||
@@ -29,7 +29,6 @@ const TPL = /*html*/`
|
||||
max-height: 600px;
|
||||
overflow: auto;
|
||||
box-shadow: 10px 10px 93px -25px black;
|
||||
contain: none;
|
||||
}
|
||||
|
||||
.attr-help td {
|
||||
@@ -138,7 +137,6 @@ const TPL = /*html*/`
|
||||
<td>
|
||||
<select class="attr-input-label-type form-control">
|
||||
<option value="text">${t("attribute_detail.text")}</option>
|
||||
<option value="textarea">${t("attribute_detail.textarea")}</option>
|
||||
<option value="number">${t("attribute_detail.number")}</option>
|
||||
<option value="boolean">${t("attribute_detail.boolean")}</option>
|
||||
<option value="date">${t("attribute_detail.date")}</option>
|
||||
@@ -344,7 +342,6 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
|
||||
private $relatedNotesList!: JQuery<HTMLElement>;
|
||||
private $relatedNotesMoreNotes!: JQuery<HTMLElement>;
|
||||
private $attrHelp!: JQuery<HTMLElement>;
|
||||
private $statusBar?: JQuery<HTMLElement>;
|
||||
|
||||
private relatedNotesSpacedUpdate!: SpacedUpdate;
|
||||
private attribute!: Attribute;
|
||||
@@ -579,24 +576,17 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isNewLayout) {
|
||||
if (!this.$statusBar) {
|
||||
this.$statusBar = $(document.body).find(".component.status-bar");
|
||||
}
|
||||
this.$widget
|
||||
.css("left", detPosition.left)
|
||||
.css("right", detPosition.right)
|
||||
.css("top", y - offset.top + 70)
|
||||
.css("max-height", outerHeight + y > height - 50 ? height - y - 50 : 10000);
|
||||
|
||||
const statusBarHeight = this.$statusBar.outerHeight() ?? 0;
|
||||
const maxHeight = document.body.clientHeight - statusBarHeight;
|
||||
if (isNewLayout) {
|
||||
this.$widget
|
||||
.css("left", offset.left + (typeof detPosition.left === "number" ? detPosition.left : 0))
|
||||
.css("top", "unset")
|
||||
.css("bottom", statusBarHeight ?? 0)
|
||||
.css("max-height", maxHeight);
|
||||
} else {
|
||||
this.$widget
|
||||
.css("left", detPosition.left)
|
||||
.css("right", detPosition.right)
|
||||
.css("top", y - offset.top + 70)
|
||||
.css("max-height", outerHeight + y > height - 50 ? height - y - 50 : 10000);
|
||||
.css("bottom", 70)
|
||||
.css("max-height", "80vh");
|
||||
}
|
||||
|
||||
if (focus === "name") {
|
||||
@@ -704,14 +694,14 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
|
||||
return "label-definition";
|
||||
} else if (attribute.name.startsWith("relation:")) {
|
||||
return "relation-definition";
|
||||
} else {
|
||||
return "label";
|
||||
}
|
||||
return "label";
|
||||
|
||||
} else if (attribute.type === "relation") {
|
||||
return "relation";
|
||||
} else {
|
||||
this.$title.text("");
|
||||
}
|
||||
this.$title.text("");
|
||||
|
||||
}
|
||||
|
||||
updateAttributeInEditor() {
|
||||
|
||||
@@ -25,7 +25,6 @@ interface NoteListProps {
|
||||
viewType: ViewTypeOptions | undefined;
|
||||
onReady?: (data: PrintReport) => void;
|
||||
onProgressChanged?(progress: number): void;
|
||||
showTextRepresentation?: boolean;
|
||||
}
|
||||
|
||||
type LazyLoadedComponent = ((props: ViewModeProps<any>) => VNode<any> | undefined);
|
||||
@@ -68,7 +67,7 @@ export default function NoteList(props: Pick<NoteListProps, "displayOnlyCollecti
|
||||
|
||||
export function SearchNoteList(props: Omit<NoteListProps, "isEnabled" | "viewType">) {
|
||||
const viewType = useNoteViewType(props.note);
|
||||
return <CustomNoteList {...props} isEnabled={true} viewType={viewType} showTextRepresentation />;
|
||||
return <CustomNoteList {...props} isEnabled={true} viewType={viewType} />;
|
||||
}
|
||||
|
||||
export function CustomNoteList({ note, viewType, isEnabled: shouldEnable, notePath, highlightedTokens, displayOnlyCollections, ntxId, onReady, onProgressChanged, ...restProps }: NoteListProps) {
|
||||
@@ -180,13 +179,11 @@ export function useNoteIds(note: FNote | null | undefined, viewType: ViewTypeOpt
|
||||
|
||||
// Refresh on alterations to the note subtree.
|
||||
useTriliumEvent("entitiesReloaded", ({ loadResults }) => {
|
||||
if (note && (
|
||||
loadResults.getNoteReorderings().includes(note.noteId)
|
||||
|| loadResults.getBranchRows().some(branch =>
|
||||
branch.parentNoteId === note.noteId
|
||||
|| noteIds.includes(branch.parentNoteId ?? ""))
|
||||
if (note && loadResults.getBranchRows().some(branch =>
|
||||
branch.parentNoteId === note.noteId
|
||||
|| noteIds.includes(branch.parentNoteId ?? ""))
|
||||
|| loadResults.getAttributeRows().some(attr => attr.name === "archived" && attr.noteId && noteIds.includes(attr.noteId))
|
||||
)) {
|
||||
) {
|
||||
refreshNoteIds();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import { describe, expect,it } from "vitest";
|
||||
|
||||
import FBranch from "../../../entities/fbranch";
|
||||
import froca from "../../../services/froca";
|
||||
import { it, describe, expect } from "vitest";
|
||||
import { buildNote } from "../../../test/easy-froca";
|
||||
import { getBoardData } from "./data";
|
||||
import FBranch from "../../../entities/fbranch";
|
||||
import froca from "../../../services/froca";
|
||||
|
||||
describe("Board data", () => {
|
||||
it("deduplicates cloned notes", async () => {
|
||||
@@ -27,7 +26,7 @@ describe("Board data", () => {
|
||||
froca.branches["note1_note2"] = branch;
|
||||
froca.getNoteFromCache("note1")!.addChild("note2", "note1_note2", false);
|
||||
const data = await getBoardData(parentNote, "status", {}, false);
|
||||
const noteIds = [...data.byColumn.values()].flat().map(item => item.note.noteId);
|
||||
const noteIds = Array.from(data.byColumn.values()).flat().map(item => item.note.noteId);
|
||||
expect(noteIds.length).toBe(3);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -75,7 +75,7 @@ export async function buildEventsForCalendar(note: FNote, e: EventSourceFuncArg)
|
||||
|
||||
|
||||
if (dateNote.hasChildren()) {
|
||||
const childNoteIds = dateNote.getChildNoteIds();
|
||||
const childNoteIds = await dateNote.getSubtreeNoteIds();
|
||||
for (const childNoteId of childNoteIds) {
|
||||
childNoteToDateMapping[childNoteId] = startDate;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user