chore: standardize placeholder values in various components and documentation, replacing "—" with "-" for consistency

This commit is contained in:
Ivan 2026-07-22 16:18:22 -05:00
parent f4d561cc86
commit fa34a0731c
No known key found for this signature in database
50 changed files with 4320 additions and 4320 deletions

View file

@ -224,7 +224,7 @@ All notable changes to this project will be documented in this file.
- **Banishment (UI)**: Blocked destinations page groups entries by identity and shows all blocked destination hashes per identity. Unblocking one unblocks the entire identity.
- **Banishment (Reticulum)**: `blackhole_identity()` is always applied when available to drop packets before LXMF delivery callbacks reach the sender, preventing "phantom deliveries" to blocked peers.
- **NomadNet file downloads**: Backtick-separated request data (e.g. ``/file/artifact`g=reticulum|r=lxmf|t=0.9.7``) is now parsed and forwarded as `var_*` request data dicts, matching upstream NomadNet behavior. Previously the raw string was passed and remote nodes could not resolve the artifact.
- **NomadNet file downloads (cancel)**: Fixed `AttributeError` when cancelling a download`RequestReceipt` has no `.cancel()`; we now cancel the underlying `Resource` if present, or mark the receipt `FAILED` and remove it from the link queue.
- **NomadNet file downloads (cancel)**: Fixed `AttributeError` when cancelling a download. `RequestReceipt` has no `.cancel()`. We now cancel the underlying `Resource` if present, or mark the receipt `FAILED` and remove it from the link queue.
- **NomadNet browser (links)**: Relative `/page/` and `/file/` URLs from the Micron parser (which include backtick parameters) are now parsed correctly so they no longer show "Unsupported URL".
- **NomadNet browser (hover)**: Links with `data-destination` now show the full URL including backtick parameters in the browser hover title.
- **Docker build**: `build-frontend` stage now installs `python3` so docs generation succeeds in `node:24-alpine`.
@ -484,7 +484,7 @@ All notable changes to this project will be documented in this file.
- **Config Editor Tool**: Added config editor tool to edit within app.
- **Repository Server Tool**: New **Tool** for the optional local file shelf to redestribute reticulum and meshchatx python wheels locally or any file you upload.
- **Dangerous Links**: The app can warn you before you open links from people you dont know, if you happen to click on it by mistake.
- **Message Rules**: New sieve tool for simple patterns—matching stuff can land in the right folder, quiet the notification bell, or other actions you pick.
- **Message Rules**: New sieve tool for simple patterns. Matching stuff can land in the right folder, quiet the notification bell, or other actions you pick.
- **Chats, Images and Reactions**: Bigger chats load faster, images are grouped and sized better, styling improvements to reactions.
- **Looks and Effects**: You can make parts of the UI transparent or enable a "glass effect" look, with clear settings to control these options.
- **Simpler Internals**: The apps settings and chat features were reorganized behind the scenes, making it easier to maintain and more stable.
@ -681,7 +681,7 @@ All notable changes to this project will be documented in this file.
- **WebSocket (`WebSocketConnection.js`)**: Heartbeat, backoff/reconnect, and **ping/pong** handling with shared helpers in **`wsConnectionSupport.js`**.
- **Context menus (Vue)**: Shared **ContextMenuPanel**, **ContextMenuItem**, **ContextMenuDivider**, and **ContextMenuSectionLabel** (`components/contextmenu/`); styling tokens in **`style.css`**. Wired into **Contacts**, **Messages** sidebar, **ConversationViewer** message menu, **NomadNetwork** sidebar (favourites, sections, announces), and **Map** (optional **header** slot for the title row).
- **LXMF emoji reactions (UI)**: **React** section in the message context menu (Columba-aligned emoji set); inbound/outbound websocket paths merge reactions onto the target message instead of a separate row; **`mergeLxmfReactionRowsIntoMessages`** when loading history; chips below the bubble with **`title`** tooltips via **`reactionReactorLabel`** (self, selected peer, sidebar conversations, else short hash).
- **Vue lint**: **`vue/no-reserved-keys`** internal **`data()`** fields renamed (peer header **ResizeObserver**, Nomad Micron partial scheduling **requestAnimationFrame** handle) so ESLint passes without reserved `_` prefixes.
- **Vue lint**: **`vue/no-reserved-keys`**: internal **`data()`** fields renamed (peer header **ResizeObserver**, Nomad Micron partial scheduling **requestAnimationFrame** handle) so ESLint passes without reserved `_` prefixes.
- **Map**: pop-out window.
- **Tools**: list-style **ToolsPage**; refreshed **Bots**, **Paper message**, **RN path**, **RN path trace**, **RNode flasher**; **About**, **Interface**, **Settings**, **Contacts**, **App** polish (loading overlays, display names, license links). Many tool and settings pages use adjusted **backgrounds and padding** for alignment with the global shell.
- **Electron**: default **context menu** for editable fields (cut/copy/paste, **spellcheck** suggestions, add to dictionary), links, and related actions; **pick file** / **pick directory** / **open path** / notifications and related **preload** helpers; loading screen refresh; CSP and **backend HTTP-only** IPC where applicable.

View file

@ -221,8 +221,8 @@ Also confirm the app is not muted in **Settings → System → Sound** and that
MeshChatX supports two levels of offline building:
1. **Cached offline builds** you already ran `make install` once and have `node_modules/`, `.venv/`, and local caches.
2. **Air-gapped (zero-network) builds** the machine has _never_ had internet. You create an offline bundle on a networked machine and transfer it.
1. **Cached offline builds**: you already ran `make install` once and have `node_modules/`, `.venv/`, and local caches.
2. **Air-gapped (zero-network) builds**: the machine has _never_ had internet. You create an offline bundle on a networked machine and transfer it.
### Cached Offline Builds

View file

@ -80,6 +80,6 @@ Skip one commit with `SKIP_TREE_RSM_HOOK=1`.
- **CI:** Automated pipelines (hosted on GitHub Actions) run dependency and configuration scanning (including **Trivy** and **pip-audit** on relevant paths), build checks, and security-relevant automated tests (authentication, path safety on dangerous operations, schema upgrades, backup/restore, rate limiting and access logging, and related areas). SRI integrity tests verify that external WASM/JS files match their declared hashes without regenerating the integrity manifests. CI will fail if you update these files without regenerating the integrity manifests.
- **Action pinning:** Third-party GitHub Actions are referenced with **pinned commit SHAs** in workflow definitions to reduce unexpected upgrades.
- **Releases:** Tagged release artifacts for Linux, Windows, and macOS are produced in CI; when the pipeline also produces Android APK and/or Flatpak bundles for the tag, those binaries are included in a separate **SLSA** attestation (`meshchatx-android-flatpak-<tag>.intoto.jsonl`). **SLSA Build Level 3style provenance** for those subjects is generated via the **generic** SLSA GitHub generator (`generator_generic_slsa3.yml` at release **v2.1.0**, with `compile-generator: true` so the builder is compiled from that tag rather than downloaded), which satisfies the **isolated builder and signed provenance** expectations for that tier; **distribution** (draft releases, mirrors) and **consumer verification** remain your operational controls, as described in upstream SLSA documentation.
- **Releases:** Tagged release artifacts for Linux, Windows, and macOS are produced in CI. When the pipeline also produces Android APK and/or Flatpak bundles for the tag, those binaries are included in a separate **SLSA** attestation (`meshchatx-android-flatpak-<tag>.intoto.jsonl`). **SLSA Build Level 3-style provenance** for those subjects is generated via the **generic** SLSA GitHub generator (`generator_generic_slsa3.yml` at release **v2.1.0**, with `compile-generator: true` so the builder is compiled from that tag rather than downloaded), which satisfies the **isolated builder and signed provenance** expectations for that tier. **Distribution** (draft releases, mirrors) and **consumer verification** remain your operational controls, as described in upstream SLSA documentation.
- **Transparency logs:** Many Sigstore flows write to the **public Rekor** log (`https://rekor.sigstore.dev` by default). **Repository-key** `*.cosign.bundle` files next to release artifacts are built **without** a Rekor entry; with **Cosign v3+**, verify them against `cosign.pub` using `cosign verify-blob-attestation` and `--insecure-ignore-tlog=true` (signature and predicate are still checked against the public key). Private-repo or air-gapped policies may require different Sigstore settings; operators should align `COSIGN_REKOR_URL` and related variables with their own governance.
- **Cosign public key:** When repository key-based signing is used, the **public** key is published in-repo as `cosign.pub` so verifiers do not need a separate out-of-band key hunt. **Key rotation:** replace the GitHub secret holding the private key and update `cosign.pub` in the repository; older releases remain verifiable with the key that was current at build time.

View file

@ -73,7 +73,7 @@ task build
Примечания:
- GitHub Actions собирает помеченные тегом релизы (Linux wheel/AppImage/deb/rpm, Windows, macOS, Flatpak, Android APK при теге на dev/master, SLSA, черновик релиза) в одном запуске: `.github/workflows/build-release.yml`; образ контейнера — `.github/workflows/docker.yml`. Android CI для веток и PR — `.github/workflows/android-build.yml`.
- GitHub Actions собирает помеченные тегом релизы (Linux wheel/AppImage/deb/rpm, Windows, macOS, Flatpak, Android APK при теге на dev/master, SLSA, черновик релиза) в одном запуске: `.github/workflows/build-release.yml`. Образ контейнера: `.github/workflows/docker.yml`. Android CI для веток и PR: `.github/workflows/android-build.yml`.
- AppImage + DEB для Linux `x64` и `arm64` собираются на GitHub; RPM собирается по возможности и выкладывается, если шаг дал артефакт.
## Docker
@ -339,7 +339,7 @@ task test
task build
```
Цели `Makefile` тонкие обёртки, делегирующие в `task` (те же команды, что выше):
Цели `Makefile` - тонкие обёртки, делегирующие в `task` (те же команды, что выше):
| Команда | Делегирует в | Описание |
| -------------- | -------------- | ------------------------------------------ |

Binary file not shown.

View file

@ -158,9 +158,9 @@ class AutoPropagationManager:
except Exception:
pass
if current_path_ok:
# Sync is likely making progress let it finish.
# Sync is likely making progress. Let it finish.
return
# Current node is unreachable stop the stuck sync so we can
# Current node is unreachable. Stop the stuck sync so we can
# look for a working alternative.
self.app.stop_propagation_node_sync(context=ctx)
# Wait briefly for the router to settle back to idle before we

View file

@ -545,14 +545,14 @@ class BugReportManager:
):
raise ValueError(
f"Invalid collector hash: '{dest_hex[:20]}{'...' if len(dest_hex) > 20 else ''}' "
f"must be 3264 hex characters (even length).",
f"must be 32-64 hex characters (even length).",
)
try:
dest_hash = bytes.fromhex(dest_hex)
except ValueError as exc:
raise ValueError(
f"Invalid collector hash: '{dest_hex[:20]}...' "
f"must be 3264 hex characters (even length).",
f"must be 32-64 hex characters (even length).",
) from exc
_payload, body = self._build_payload(args)

View file

@ -8,7 +8,7 @@
{
"name": "aiohttp",
"version": "3.14.1",
"author": "",
"author": "-",
"license": "Apache-2.0 AND MIT"
},
{
@ -32,7 +32,7 @@
{
"name": "audioop-lts",
"version": "0.2.2",
"author": "",
"author": "-",
"license": "PSF-2.0"
},
{
@ -170,7 +170,7 @@
{
"name": "rns-filesync",
"version": "1.0.0",
"author": "",
"author": "-",
"license": "BSD-2-Clause"
},
{

View file

@ -62,55 +62,55 @@
{
"name": "@csstools/color-helpers",
"version": "6.0.2",
"author": "",
"author": "-",
"license": "MIT-0"
},
{
"name": "@csstools/css-calc",
"version": "3.2.0",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "@csstools/css-color-parser",
"version": "4.1.0",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "@csstools/css-parser-algorithms",
"version": "4.0.0",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "@csstools/css-syntax-patches-for-csstree",
"version": "1.1.3",
"author": "",
"author": "-",
"license": "MIT-0"
},
{
"name": "@csstools/css-tokenizer",
"version": "4.0.0",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "@egjs/hammerjs",
"version": "2.0.17",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "@electron-internal/extract-zip",
"version": "1.0.1",
"author": "",
"author": "-",
"license": "BSD-2-Clause"
},
{
"name": "@electron/asar",
"version": "3.4.1",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -140,7 +140,7 @@
{
"name": "@electron/rebuild",
"version": "4.0.4",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -182,7 +182,7 @@
{
"name": "@eslint/config-helpers",
"version": "0.4.2",
"author": "",
"author": "-",
"license": "Apache-2.0"
},
{
@ -200,7 +200,7 @@
{
"name": "@eslint/js",
"version": "9.39.5",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -230,7 +230,7 @@
{
"name": "@gar/promise-retry",
"version": "1.0.3",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -362,7 +362,7 @@
{
"name": "@mapbox/unitbezier",
"version": "0.0.1",
"author": "",
"author": "-",
"license": "BSD-2-Clause"
},
{
@ -410,7 +410,7 @@
{
"name": "@one-ini/wasm",
"version": "0.1.1",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -428,7 +428,7 @@
{
"name": "@oxc-resolver/binding-linux-x64-gnu",
"version": "11.24.2",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -464,7 +464,7 @@
{
"name": "@pkgjs/parseargs",
"version": "0.11.0",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -488,13 +488,13 @@
{
"name": "@rolldown/binding-linux-x64-gnu",
"version": "1.1.5",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "@rolldown/pluginutils",
"version": "1.0.0",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -518,31 +518,31 @@
{
"name": "@tailwindcss/forms",
"version": "0.5.11",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "@tailwindcss/node",
"version": "4.3.3",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "@tailwindcss/oxide",
"version": "4.3.3",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "@tailwindcss/oxide-linux-x64-gnu",
"version": "4.3.3",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "@tailwindcss/vite",
"version": "4.3.3",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -560,85 +560,85 @@
{
"name": "@types/cacheable-request",
"version": "6.0.1",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "@types/chai",
"version": "5.2.3",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "@types/debug",
"version": "4.1.6",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "@types/deep-eql",
"version": "4.0.2",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "@types/estree",
"version": "1.0.0",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "@types/fs-extra",
"version": "9.0.13",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "@types/hammerjs",
"version": "2.0.46",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "@types/http-cache-semantics",
"version": "4.0.0",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "@types/json-schema",
"version": "7.0.15",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "@types/keyv",
"version": "3.0.0",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "@types/node",
"version": "0.0.0",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "@types/rbush",
"version": "4.0.0",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "@types/responselike",
"version": "1.0.0",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "@types/trusted-types",
"version": "2.0.7",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -656,67 +656,67 @@
{
"name": "@vitest/expect",
"version": "4.1.10",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "@vitest/mocker",
"version": "4.1.10",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "@vitest/pretty-format",
"version": "4.1.10",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "@vitest/runner",
"version": "4.1.10",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "@vitest/snapshot",
"version": "4.1.10",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "@vitest/spy",
"version": "4.1.10",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "@vitest/ui",
"version": "4.1.10",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "@vitest/utils",
"version": "4.1.10",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "@volar/language-core",
"version": "2.4.28",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "@volar/source-map",
"version": "2.4.28",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "@volar/typescript",
"version": "2.4.28",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -752,7 +752,7 @@
{
"name": "@vue/language-core",
"version": "3.3.7",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -800,7 +800,7 @@
{
"name": "@zarrita/storage",
"version": "0.2.0",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -818,13 +818,13 @@
{
"name": "acorn",
"version": "0.11.0",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "acorn-jsx",
"version": "5.3.2",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -842,7 +842,7 @@
{
"name": "alien-signals",
"version": "3.2.1",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -872,7 +872,7 @@
{
"name": "argparse",
"version": "2.0.1",
"author": "",
"author": "-",
"license": "Python-2.0"
},
{
@ -932,7 +932,7 @@
{
"name": "balanced-match",
"version": "1.0.0",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -968,19 +968,19 @@
{
"name": "boolean",
"version": "3.0.1",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "brace-expansion",
"version": "1.1.12",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "buffer-from",
"version": "1.0.0",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -1040,7 +1040,7 @@
{
"name": "chalk",
"version": "4.1.1",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -1052,7 +1052,7 @@
{
"name": "chromium-pickle-js",
"version": "0.2.0",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -1124,7 +1124,7 @@
{
"name": "component-emitter",
"version": "2.0.0",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -1160,7 +1160,7 @@
{
"name": "cross-dirname",
"version": "0.1.0",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -1268,7 +1268,7 @@
{
"name": "dijkstrajs",
"version": "1.0.1",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -1292,7 +1292,7 @@
{
"name": "dotenv",
"version": "16.6.1",
"author": "",
"author": "-",
"license": "BSD-2-Clause"
},
{
@ -1370,7 +1370,7 @@
{
"name": "electron-winstaller",
"version": "5.4.0",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -1514,7 +1514,7 @@
{
"name": "eslint-scope",
"version": "8.2.0",
"author": "",
"author": "-",
"license": "BSD-2-Clause"
},
{
@ -1550,13 +1550,13 @@
{
"name": "esrecurse",
"version": "4.3.0",
"author": "",
"author": "-",
"license": "BSD-2-Clause"
},
{
"name": "estraverse",
"version": "5.1.0",
"author": "",
"author": "-",
"license": "BSD-2-Clause"
},
{
@ -1568,7 +1568,7 @@
{
"name": "esutils",
"version": "2.0.3",
"author": "",
"author": "-",
"license": "BSD-2-Clause"
},
{
@ -1580,7 +1580,7 @@
{
"name": "expect-type",
"version": "1.3.0",
"author": "",
"author": "-",
"license": "Apache-2.0"
},
{
@ -1802,13 +1802,13 @@
{
"name": "got",
"version": "11.8.6",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "graceful-fs",
"version": "4.1.2",
"author": "",
"author": "-",
"license": "ISC"
},
{
@ -1892,7 +1892,7 @@
{
"name": "immediate",
"version": "3.0.5",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -1916,7 +1916,7 @@
{
"name": "inherits",
"version": "2.0.1",
"author": "",
"author": "-",
"license": "ISC"
},
{
@ -2018,7 +2018,7 @@
{
"name": "isbinaryfile",
"version": "4.0.8",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -2066,7 +2066,7 @@
{
"name": "jiti",
"version": "2.4.2",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -2096,7 +2096,7 @@
{
"name": "jsdom",
"version": "29.1.1",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -2144,7 +2144,7 @@
{
"name": "jsqr",
"version": "1.4.0",
"author": "",
"author": "-",
"license": "Apache-2.0"
},
{
@ -2198,19 +2198,19 @@
{
"name": "lie",
"version": "3.3.0",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "lightningcss",
"version": "1.32.0",
"author": "",
"author": "-",
"license": "MPL-2.0"
},
{
"name": "lightningcss-linux-x64-gnu",
"version": "1.32.0",
"author": "",
"author": "-",
"license": "MPL-2.0"
},
{
@ -2258,7 +2258,7 @@
{
"name": "magicast",
"version": "0.5.2",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -2312,7 +2312,7 @@
{
"name": "micron-parser",
"version": "0.0.0",
"author": "",
"author": "-",
"license": "Unknown"
},
{
@ -2324,13 +2324,13 @@
{
"name": "mime-db",
"version": "1.52.0",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "mime-types",
"version": "2.1.35",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -2420,13 +2420,13 @@
{
"name": "ms",
"version": "2.0.0",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "muggle-string",
"version": "0.4.1",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -2444,7 +2444,7 @@
{
"name": "negotiator",
"version": "1.0.0",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -2528,13 +2528,13 @@
{
"name": "ol",
"version": "10.9.0",
"author": "",
"author": "-",
"license": "BSD-2-Clause"
},
{
"name": "ol-mapbox-style",
"version": "13.4.1",
"author": "",
"author": "-",
"license": "BSD-2-Clause"
},
{
@ -2564,7 +2564,7 @@
{
"name": "oxc-resolver",
"version": "11.24.2",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -2618,13 +2618,13 @@
{
"name": "pako",
"version": "1.0.2",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "pako",
"version": "2.0.4",
"author": "",
"author": "-",
"license": "(MIT AND Zlib)"
},
{
@ -2678,7 +2678,7 @@
{
"name": "pathe",
"version": "2.0.3",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -2732,7 +2732,7 @@
{
"name": "pngjs",
"version": "5.0.0",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -2744,13 +2744,13 @@
{
"name": "postcss-selector-parser",
"version": "7.1.4",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "postject",
"version": "1.0.0-alpha.6",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -2768,7 +2768,7 @@
{
"name": "prettier-linter-helpers",
"version": "1.0.1",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -2786,7 +2786,7 @@
{
"name": "process-nextick-args",
"version": "1.0.0",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -2876,7 +2876,7 @@
{
"name": "readable-stream",
"version": "1.0.31",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -2972,7 +2972,7 @@
{
"name": "rolldown",
"version": "1.1.5",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -3128,7 +3128,7 @@
{
"name": "source-map-support",
"version": "0.5.19",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -3158,7 +3158,7 @@
{
"name": "std-env",
"version": "4.0.0-rc.1",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -3176,7 +3176,7 @@
{
"name": "string_decoder",
"version": "0.10.24",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -3224,7 +3224,7 @@
{
"name": "tailwindcss",
"version": "4.3.3",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -3272,7 +3272,7 @@
{
"name": "tinybench",
"version": "2.9.0",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -3290,13 +3290,13 @@
{
"name": "tinyqueue",
"version": "3.0.0",
"author": "",
"author": "-",
"license": "ISC"
},
{
"name": "tinyrainbow",
"version": "3.1.0",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -3380,13 +3380,13 @@
{
"name": "undici",
"version": "7.28.0",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "undici-types",
"version": "7.16.0",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -3404,7 +3404,7 @@
{
"name": "unzipit",
"version": "2.0.0",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -3440,19 +3440,19 @@
{
"name": "uuid",
"version": "14.0.1",
"author": "",
"author": "-",
"license": "MIT"
},
{
"name": "vis-data",
"version": "7.1.10",
"author": "",
"author": "-",
"license": "(Apache-2.0 OR MIT)"
},
{
"name": "vis-network",
"version": "9.1.13",
"author": "",
"author": "-",
"license": "(Apache-2.0 OR MIT)"
},
{
@ -3494,7 +3494,7 @@
{
"name": "vue-component-type-helpers",
"version": "3.0.0",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -3518,7 +3518,7 @@
{
"name": "vue-tsc",
"version": "3.3.7",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -3530,7 +3530,7 @@
{
"name": "w3c-xmlserializer",
"version": "5.0.0",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -3542,7 +3542,7 @@
{
"name": "web-worker",
"version": "1.5.0",
"author": "",
"author": "-",
"license": "Apache-2.0"
},
{
@ -3662,7 +3662,7 @@
{
"name": "yargs",
"version": "12.0.5",
"author": "",
"author": "-",
"license": "MIT"
},
{
@ -3680,7 +3680,7 @@
{
"name": "zarrita",
"version": "0.7.1",
"author": "",
"author": "-",
"license": "MIT"
},
{

View file

@ -13,7 +13,7 @@ function formatLabel(api, key, params = {}) {
function shortHash(hash) {
if (!hash || hash.length < 12) {
return hash || "";
return hash || "-";
}
return `${hash.slice(0, 10)}${hash.slice(-6)}`;
}
@ -205,7 +205,7 @@ export async function activate(api) {
{
type: "text",
variant: "caption",
value: entry.name || "",
value: entry.name || "-",
},
{
type: "button",
@ -319,7 +319,7 @@ export async function activate(api) {
{
type: "text",
variant: "subtitle",
value: entry.title || "",
value: entry.title || "-",
},
{
type: "text",
@ -335,7 +335,7 @@ export async function activate(api) {
String(entry.description || "").slice(
0,
160
) || "",
) || "-",
},
],
},

View file

@ -33,7 +33,7 @@
"no_preview": "Preview logs to review what will be sent.",
"preview_stats": "{lines} lines, {chars} characters",
"send_ok": "Report sent ({bytes} bytes).",
"invalid_hash": "\"{value}\" is not a valid collector hash. Click 'Use my collector' to auto-fill, or paste a 3264 character hex hash.",
"invalid_hash": "\"{value}\" is not a valid collector hash. Click 'Use my collector' to auto-fill, or paste a 32-64 character hex hash.",
"collector_started": "Collector started.",
"collector_stopped": "Collector stopped.",
"announce_ok": "Collector announced as mcx-bugs-v1.",

View file

@ -396,7 +396,7 @@ class MemoryDiagnostics:
type_name: str,
max_results: int = 20,
) -> list[dict[str, Any]]:
"""Find referrers of objects of a given type — useful to trace who holds references."""
"""Find referrers of objects of a given type. Useful to trace who holds references."""
matches: list[Any] = []
try:
for obj in gc.get_objects():

View file

@ -42,7 +42,7 @@ def _license_from_metadata(meta: importlib.metadata.Metadata) -> str:
for line in classifiers:
if line.startswith("License ::"):
return line.split("::", 1)[-1].strip()
return ""
return "-"
def _author_from_metadata(meta: importlib.metadata.Metadata) -> str:
@ -55,7 +55,7 @@ def _author_from_metadata(meta: importlib.metadata.Metadata) -> str:
m = (meta.get("Maintainer") or "").strip()
if m:
return m
return ""
return "-"
def _dist_for_requirement_name(name: str) -> importlib.metadata.Distribution | None:
@ -161,8 +161,8 @@ def _bundled_vendor_license_row(
if name != dist_name and name != lookup_name:
return None
version = proj.get("version")
version_s = version.strip() if isinstance(version, str) and version.strip() else ""
author = ""
version_s = version.strip() if isinstance(version, str) and version.strip() else "-"
author = "-"
authors = proj.get("authors")
if isinstance(authors, list) and authors:
first = authors[0]
@ -175,11 +175,11 @@ def _bundled_vendor_license_row(
author = an or ae
lic = proj.get("license")
if isinstance(lic, dict):
license_s = str(lic.get("text") or lic.get("file") or "").strip() or ""
license_s = str(lic.get("text") or lic.get("file") or "-").strip() or "-"
elif isinstance(lic, str) and lic.strip():
license_s = lic.strip()
else:
license_s = ""
license_s = "-"
return {
"name": dist_name,
"version": version_s,
@ -281,7 +281,7 @@ def _license_from_package_json(data: dict[str, Any]) -> str:
t = first.get("type")
if isinstance(t, str) and t.strip():
return t.strip()
return ""
return "-"
def _author_from_package_json(data: dict[str, Any]) -> str:
@ -307,7 +307,7 @@ def _author_from_package_json(data: dict[str, Any]) -> str:
return f"{name} <{email}>"
if name or email:
return name or email
return ""
return "-"
def _workspace_root_npm_identity(repo_root: Path) -> tuple[str | None, str | None]:
@ -436,10 +436,10 @@ def _flatten_pnpm_licenses_json(data: dict[str, Any]) -> list[dict[str, Any]]:
name = pkg.get("name") or "?"
versions = pkg.get("versions") or []
version = versions[0] if versions else "?"
author = pkg.get("author") or ""
author = pkg.get("author") or "-"
if not isinstance(author, str):
author = str(author)
lic = pkg.get("license") or _license_key or ""
lic = pkg.get("license") or _license_key or "-"
out.append(
{
"name": name,
@ -552,8 +552,8 @@ def render_third_party_notices(payload: dict[str, Any]) -> str:
continue
name = str(row.get("name", "?"))
version = str(row.get("version", "?"))
author = str(row.get("author", ""))
license_name = str(row.get("license", ""))
author = str(row.get("author", "-"))
license_name = str(row.get("license", "-"))
lines.append(f"{name} {version}")
lines.append(f" License: {license_name}")
lines.append(f" Author: {author}")

View file

@ -1657,7 +1657,7 @@ export default {
userFacing,
};
// Open peers are mark-as-read by ConversationViewer; still refresh for other peers.
// Open peers are mark-as-read by ConversationViewer. Still refresh for other peers.
if (isIncoming && userFacing && !sourceOpen) {
this.updateUnreadConversationsCount();
}
@ -2121,7 +2121,7 @@ export default {
this.ringtonePlayer.play().catch((e) => {
if (e?.name === "NotAllowedError") {
// Browser autoplay policy blocked playback until user gesture.
// Stop retry spam; we retry once user interacts again.
// Stop retry spam. We retry once user interacts again.
this.ringtoneAutoplayBlocked = true;
return;
}
@ -2357,7 +2357,7 @@ export default {
return;
}
} catch {
/* not a valid URL; continue */
/* not a valid URL, continue */
}
if (/^(meshchatx|meshchat):\/\/map\b/i.test(normalizedUrl)) {
WebSocketConnection.send(

View file

@ -1878,7 +1878,7 @@ export default {
},
formatRecoveryResult(value) {
if (value === null || value === undefined) {
return "";
return "-";
}
if (Array.isArray(value)) {
return value.join(", ");

View file

@ -198,7 +198,7 @@
<span class="text-gray-500">IP</span> {{ row.client_ip }}
</div>
<div class="text-gray-600 dark:text-gray-400 break-all max-sm:text-[8px]">
<span class="text-gray-500">UA</span> {{ row.user_agent || "" }}
<span class="text-gray-500">UA</span> {{ row.user_agent || "-" }}
</div>
<div v-if="row.detail" class="text-gray-500 max-sm:text-[8px] sm:text-[10px]">
{{ row.detail }}

View file

@ -528,7 +528,7 @@
<input
v-model="newInterfaceNetworkDevice"
type="text"
placeholder="e.g. eth0 (real OS interface; leave empty to use Listen IP only)"
placeholder="e.g. eth0 (real OS interface, leave empty to use Listen IP only)"
class="input-field"
/>
</div>
@ -1333,7 +1333,7 @@
</div>
</div>
<!-- LocalInterface: IPC path used internally by RNS; optional external module -->
<!-- LocalInterface: IPC path used internally by RNS. Optional external module -->
<div v-if="newInterfaceType === 'LocalInterface'" class="space-y-4">
<div class="text-sm text-gray-800 dark:text-zinc-200 leading-snug">
{{ $t("interfaces.loopback_local_title") }}

View file

@ -217,8 +217,8 @@
>
</div>
<div class="text-sm text-gray-600 dark:text-gray-300">
Discovery runs continually; heard announces stay listed. Connected entries show
a green pill; disconnected entries are dimmed with a red label.
Discovery runs continually. Heard announces stay listed. Connected entries show
a green pill. Disconnected entries are dimmed with a red label.
</div>
</div>
<div class="flex flex-wrap gap-2 items-center shrink-0 min-w-0">
@ -900,7 +900,7 @@ export default {
},
discoveredEmptyMessage() {
if (!this.isReticulumRunning) {
return "LXMF/Reticulum is not running; discovery cannot listen for announces.";
return "LXMF/Reticulum is not running. Discovery cannot listen for announces.";
}
if (!this.discoveryConfig.discover_interfaces) {
return "Discovery is disabled. Enable it to start listening for announces.";

View file

@ -437,7 +437,7 @@
</div>
</div>
<!-- scale line: bottom-right so it never stacks over the lat/lon readout (bottom-left); hidden on small screens -->
<!-- scale line: bottom-right so it never stacks over the lat/lon readout (bottom-left). Hidden on small screens -->
<div
v-show="!isMobileScreen"
ref="scaleLineMount"
@ -4673,7 +4673,7 @@ export default {
this.onVectorExchangeImport({ features, merge: true });
} catch (e) {
console.error("Map drop import failed:", e);
ToastUtils.error(this.$t("map.vector_import_failed") + ` ${file.name}`);
ToastUtils.error(this.$t("map.vector_import_failed") + ` - ${file.name}`);
}
}
},

View file

@ -2074,7 +2074,7 @@ export default {
const d = { ...this.rawMessageData };
const c = d.content;
if (typeof c === "string" && c.length > MESSAGE_BODY_MAX_DISPLAY_CHARS) {
d.content = `[Omitted ${c.length} characters — use Copy full text above]`;
d.content = `[Omitted ${c.length} characters. Use Copy full text above]`;
}
try {
return JSON.stringify(d, null, 2);
@ -3117,8 +3117,8 @@ export default {
showFooter: Boolean(hasTr),
showOriginalLink: hasTr && !tr.showOriginal,
showTranslationLink: hasTr && tr.showOriginal,
fromCode: (tr && tr.resolvedSourceLang) || "",
toCode: (tr && tr.targetLang) || "",
fromCode: (tr && tr.resolvedSourceLang) || "-",
toCode: (tr && tr.targetLang) || "-",
messageHash: h,
singleEmoji,
};

View file

@ -580,7 +580,7 @@ export default {
return (bytes / (1024 * 1024)).toFixed(1) + " MB";
},
formatMeshUptime(seconds) {
if (seconds == null || seconds < 0) return "";
if (seconds == null || seconds < 0) return "-";
let s = Math.floor(seconds);
if (s < 60) return `${s}s`;
if (s < 3600) return `${Math.floor(s / 60)}m`;

View file

@ -1790,7 +1790,7 @@ export default {
},
formatUptime(seconds) {
if (seconds == null || seconds < 0) {
return "";
return "-";
}
let s = Math.floor(seconds);
if (s < 60) {
@ -2545,7 +2545,7 @@ export default {
try {
await window.api.post(`/api/v1/rrc/hubs/${hubHash}/rooms/${this.encodeRoom(room)}/read`);
} catch {
// GET messages already marks active/read on the server; ignore duplicate failures.
// GET messages already marks active/read on the server. Ignore duplicate failures.
}
if (refreshHubs) {
await this.fetchHubs();

View file

@ -881,7 +881,7 @@ export default {
},
formatUptime(seconds) {
if (seconds == null || seconds < 0) {
return "";
return "-";
}
let s = Math.floor(seconds);
if (s < 60) {

View file

@ -627,7 +627,7 @@ export default {
const f = event.target.files?.[0];
event.target.value = "";
if (!f) return;
// Browsers only expose the basename; require an explicit full path.
// Browsers only expose the basename. Require an explicit full path.
this.sendFilePath = "";
DialogUtils.alert(this.$t("rncp.web_path_hint"));
},

View file

@ -30,7 +30,7 @@
{{ $t(row.labelKey) }}
</dt>
<dd class="font-mono text-gray-800 dark:text-zinc-200 break-all">
{{ row.value || "" }}
{{ row.value || "-" }}
</dd>
</div>
</dl>

View file

@ -3133,8 +3133,8 @@
{{ $t("app.web_listen_address") }}
</div>
<div class="font-mono text-gray-900 dark:text-gray-100">
{{ serverSecurity.listen_host || "" }}:{{
serverSecurity.listen_port ?? ""
{{ serverSecurity.listen_host || "-" }}:{{
serverSecurity.listen_port ?? "-"
}}
</div>
</div>
@ -3564,7 +3564,7 @@
$t("app.run_local_node_description")
}}</span>
<span class="setting-toggle__hint monospace-field">{{
config.lxmf_local_propagation_node_address_hash || ""
config.lxmf_local_propagation_node_address_hash || "-"
}}</span>
</span>
</label>

View file

@ -244,7 +244,7 @@
<span v-else-if="lxmfAddressFor(bot)">{{
$t("bots.never_announced")
}}</span>
<span v-else></span>
<span v-else>-</span>
</dd>
</div>
</dl>

View file

@ -339,7 +339,7 @@ export default {
try {
await this._loadScript(lib);
} catch {
// continue best-effort; loadVendorLibraries is best-effort and
// continue best-effort. loadVendorLibraries is best-effort and
// missing assets surface later through clear error toasts
}
}

View file

@ -79,7 +79,7 @@ export default class LinkUtils {
/**
* Detects and wraps Reticulum (NomadNet and LXMF) links in HTML.
* Supports nomadnet://<hash>, nomadnet@<hash>, lxmf://<hash>, lxmf@<hash>, lxmf:<hash>,
* and bare <hash>:/path (NomadNet path form only no bare hash without prefix).
* and bare <hash>:/path (NomadNet path form only, no bare hash without prefix).
*/
static renderReticulumLinks(text) {
if (!text) return "";

View file

@ -61,7 +61,7 @@ export default class MarkdownRenderer {
// Links
text = LinkUtils.renderAllLinks(text);
// Restore inline code then fenced blocks (single pass; avoid O(n*m) replace loops)
// Restore inline code then fenced blocks (single pass, avoid O(n*m) replace loops)
text = text.replace(/\[\[IC(\d+)\]\]/g, (_m, idx) => inline_codes[Number(idx)] ?? _m);
text = text.replace(/\[\[CB(\d+)\]\]/g, (_m, idx) => code_blocks[Number(idx)] ?? _m);

View file

@ -49,7 +49,7 @@ function normalizeMarkdownInput(md) {
}
let s = String(md);
s = s.replace(/\r\n/g, "\n");
// CommonMark requires a space after # for ATX headings; "#Title" is not a heading
// CommonMark requires a space after # for ATX headings. "#Title" is not a heading
s = s.replace(/^(\s{0,3})(#{1,6})([^\s#])/gm, "$1$2 $3");
return s;
}

View file

@ -45,7 +45,7 @@ function writeJson(key, value) {
}
window.localStorage.setItem(key, JSON.stringify(value));
} catch {
// persistence is best-effort; ignore quota or availability errors
// persistence is best-effort. Ignore quota or availability errors
}
}

View file

@ -4,7 +4,7 @@
*/
/**
* Browsers set `false` on http://0.0.0.0 and similar; `undefined` in some test envs is treated as allowed.
* Browsers set `false` on http://0.0.0.0 and similar. `undefined` in some test envs is treated as allowed.
* @returns {boolean}
*/
export function isWindowSecureContext() {

View file

@ -148,7 +148,7 @@ function colorFromNode(node) {
if (rgb) return rgb;
}
if (c && typeof c === "object") {
// Border is the vivid badge color; background is a pale tint for vis-network.
// Border is the vivid badge color. Background is a pale tint for vis-network.
const fill = c.border || c.background;
const rgb = hexToRgb01(fill);
if (rgb) return rgb;

View file

@ -195,7 +195,7 @@
"run_local_node": "Einen lokalen Propagationsknoten betreiben",
"run_local_node_description": "MeshChat wird einen Knoten unter Verwendung dieses lokalen Ziel-Hashs ankündigen und warten.",
"preferred_propagation_node": "Bevorzugter Propagationsknoten",
"preferred_node_placeholder": "Ziel-Hash, z.B. a39610c89d18bb48c73e429582423c24",
"preferred_node_placeholder": "Ziel-Hash, z.B. A39610c89d18bb48c73e429582423c24",
"fallback_node_description": "Nachrichten weichen auf diesen Knoten aus, wenn die direkte Zustellung fehlschlägt.",
"auto_select_node": "Besten Knoten automatisch auswählen",
"auto_select_node_description": "Automatisch den besten verfügbaren Propagationsknoten basierend auf den Netzwerkhops finden und dorthin wechseln.",
@ -356,7 +356,7 @@
"announce_store_lxst": "LXST Telefonie (lxst.telephony)",
"announce_store_nomad": "NomadNet-Knoten (nomadnetwork.node)",
"announce_store_prop": "Verteilerknoten (lxmf.propagation)",
"announce_max_stored_heading": "Max. gespeichert pro Aspekt (Datenbank)",
"announce_max_stored_heading": "Max. Gespeichert pro Aspekt (Datenbank)",
"announce_fetch_limit_heading": "Standard-Seitengröße (API)",
"announce_search_max_fetch": "Max. Ankündigungen für Suche",
"announce_search_max_fetch_hint": "Maximale Zeilen aus der Datenbank bei Textsuche (pro Anfrage).",
@ -395,7 +395,7 @@
"csp_settings": "Content-Security-Policy (CSP)",
"csp_description": "Fügen Sie manuell erlaubte Domänen für verschiedene Ressourcen hinzu. Dies ist nützlich für eigene Kartenserver, Bots oder externe Integrationen.",
"csp_extra_connect_src": "Zusätzliche Connect-Quellen",
"csp_extra_connect_src_description": "Zusätzliche Quellen für fetch/Websocket-Verbindungen (z. B. https://api.example.com).",
"csp_extra_connect_src_description": "Zusätzliche Quellen für fetch/Websocket-Verbindungen (z. B. Https://api.example.com).",
"csp_extra_img_src": "Zusätzliche Bildquellen",
"csp_extra_img_src_description": "Zusätzliche Quellen für Bilder und Kacheln.",
"csp_extra_frame_src": "Zusätzliche Frame-Quellen",
@ -416,7 +416,7 @@
"location_manual_lon": "Längengrad",
"location_manual_alt": "Höhe (m)",
"telemetry_enabled": "Telemetrie aktiviert",
"telemetry_description": "Erlaubt MeshChatX das Senden und Empfangen von Telemetriedaten, wie z. B. das Beantworten von Standortanfragen vertrauenswürdiger Kontakte.",
"telemetry_description": "Erlaubt MeshChatX das Senden und Empfangen von Telemetriedaten, wie z. B. Das Beantworten von Standortanfragen vertrauenswürdiger Kontakte.",
"telemetry_trusted_peers": "Vertrauenswürdige Telemetrie-Peers",
"telemetry_no_trusted_peers": "Keine vertrauenswürdigen Peers konfiguriert. Vertrauen Sie Peers aus dem Chat-Menü, um ihnen zu erlauben, Ihren Standort abzufragen.",
"telemetry_revoke_trust": "Vertrauen entziehen",
@ -435,9 +435,9 @@
"map_overlay_limits_desc": "Schutzgrenzen für NomadNet- und RNGit-Importe von KMZ/KML/GeoJSON. Werte werden auf sichere Bereiche begrenzt.",
"map_overlay_max_bytes": "Max. Overlay-Dateigröße (Bytes)",
"map_overlay_max_features": "Max. Features pro Overlay",
"map_overlay_max_kmz_uncompressed_bytes": "Max. unkomprimierte KMZ-Größe (Bytes)",
"map_overlay_max_kmz_uncompressed_bytes": "Max. Unkomprimierte KMZ-Größe (Bytes)",
"map_overlay_max_sources": "Max. Overlay-Quellen",
"map_overlay_max_concurrent_jobs": "Max. gleichzeitige Overlay-Jobs",
"map_overlay_max_concurrent_jobs": "Max. Gleichzeitige Overlay-Jobs",
"map_overlay_path_timeout_seconds": "Timeout für Pfadsuche (Sekunden)",
"map_overlay_transfer_timeout_seconds": "Timeout für Übertragung (Sekunden)",
"map_overlay_job_timeout_seconds": "Timeout für Job (Sekunden)",
@ -486,7 +486,7 @@
"copy_rpc_config": "RPC-Konfiguration kopieren",
"connected_to_shared_instance": "Dieser MeshChatX-Prozess ist mit einer externen gemeinsam genutzten Reticulum-Instanz verbunden. Bearbeiten Sie die Konfiguration dieser Instanz, um die Share/RPC-Einstellungen zu ändern.",
"copy_failed": "In Zwischenablage kopieren fehlgeschlagen",
"rpc_key_hidden": "Verborgen — tippen zum Anzeigen",
"rpc_key_hidden": "Verborgen. Tippen zum Anzeigen",
"rpc_key_show": "RPC-Schlüssel anzeigen",
"rpc_key_hide": "RPC-Schlüssel verbergen",
"refresh_community_interfaces": "Von directory.rns.recipes aktualisieren",
@ -599,7 +599,7 @@
"file_too_large_video": "WEBM-Video-Sticker dürfen höchstens 256 KB groß sein.",
"invalid_dimensions": "Sticker dürfen höchstens 512×512 Pixel haben, eine Seite muss genau 512 sein.",
"invalid_duration": "Animierte und Video-Sticker dürfen höchstens 3 Sekunden lang sein.",
"invalid_fps": "Animierte Sticker: 3060 FPS, Video-Sticker bis 30 FPS.",
"invalid_fps": "Animierte Sticker: 30-60 FPS, Video-Sticker bis 30 FPS.",
"invalid_codec": "Video-Sticker müssen den Codec VP9 verwenden.",
"invalid_audio": "Video-Sticker dürfen keinen Audiostream enthalten.",
"invalid_tgs": "TGS-Animation konnte nicht gelesen werden.",
@ -613,7 +613,7 @@
"title_label": "Titel",
"title_placeholder": "Mein Paket",
"short_name_label": "Kurzname",
"short_name_placeholder": "z. B. katzen",
"short_name_placeholder": "z. B. Katzen",
"description_label": "Beschreibung",
"type_label": "Typ",
"type_static": "Statisch",
@ -1047,7 +1047,7 @@
"contact_name_optional": "Kontaktname (optional)",
"contact_name_placeholder": "z.B. Feldknoten",
"hash_or_uri": "LXMF-Hash oder URI",
"hash_or_uri_placeholder": "32-Zeichen-Hash, lxmf://... oder lxma://...",
"hash_or_uri_placeholder": "32-Zeichen-Hash, lxmf://... Oder lxma://...",
"paste": "Einfügen",
"failed_load_contacts": "Kontakte konnten nicht geladen werden",
"invalid_contact_input": "Ungültige Eingabe. 32-Zeichen-Hash oder lxma://-URI verwenden.",
@ -1467,8 +1467,8 @@
"tile_connectivity_retry": "Kacheln erneut laden",
"tile_connectivity_use_offline": "Offline-Modus",
"tile_connectivity_dismiss": "Schließen",
"tile_failover_trying": "Kartenkacheln fehlgeschlagen; versuche {provider}…",
"tile_failover_offline": "Online-Kacheln nicht verfügbar; wechsle in den Offline-Modus",
"tile_failover_trying": "Kartenkacheln fehlgeschlagen. Versuche {provider}…",
"tile_failover_offline": "Online-Kacheln nicht verfügbar. Wechsle in den Offline-Modus",
"search_no_results": "Keine Ergebnisse gefunden",
"custom_tile_server_unavailable": "Benutzerdefinierter Kachelserver ist im Offline-Modus nicht erreichbar",
"custom_nominatim_unavailable": "Benutzerdefinierter Nominatim-Server ist im Offline-Modus nicht erreichbar",
@ -1645,7 +1645,7 @@
"snr": "SNR {snr}",
"stamp_cost": "Stempelkosten {cost}",
"stamp_ticket_valid": "Ausgehendes Stempel-Ticket aktiv (sofortiger Versand). Läuft ab {expires}.",
"stamp_ticket_expired": "Stempel-Ticket abgelaufen; die nächste Nachricht kann einen Proof-of-Work erfordern.",
"stamp_ticket_expired": "Stempel-Ticket abgelaufen. Die nächste Nachricht kann einen Proof-of-Work erfordern.",
"pop_out_chat": "Chat auslagern",
"open_in_split": "In geteilter Ansicht öffnen",
"select_conversation_for_pane": "Wähle eine Unterhaltung, um sie hier zu öffnen",
@ -1675,7 +1675,7 @@
"path_loading": "Pfad wird geprüft…",
"path_stale_label": "veraltet",
"path_unresponsive_label": "ohne Antwort",
"path_stale_hint": "Dieser Pfadeintrag ist abgelaufen und wird vor dem nächsten Senden ggf. neu ermittelt.",
"path_stale_hint": "Dieser Pfadeintrag ist abgelaufen und wird vor dem nächsten Senden ggf. Neu ermittelt.",
"path_unresponsive_hint": "Reticulum hat diesen Pfad als nicht ansprechbar markiert.",
"path_info_title": "Pfadinformation",
"path_already_available": "Pfad ist bereits verfügbar",
@ -1760,7 +1760,7 @@
"folders_imported": "Ordner importiert",
"failed_import_folders": "Ordner konnten nicht importiert werden",
"failed_read_clipboard": "Lesen aus Zwischenablage fehlgeschlagen",
"clipboard_read_requires_secure_context": "Zum Lesen der Zwischenablage wird eine sichere Seite benötigt (https oder http://127.0.0.1). Die Verwendung von http://0.0.0.0 oder einem anderen nicht-lokalen HTTP-Ursprung blockiert die Clipboard-API öffnen Sie die App auf 127.0.0.1 oder https, oder fügen Sie mit Strg+V ein.",
"clipboard_read_requires_secure_context": "Zum Lesen der Zwischenablage wird eine sichere Seite benötigt (https oder http://127.0.0.1). Die Verwendung von http://0.0.0.0 oder einem anderen nicht-lokalen HTTP-Ursprung blockiert die Clipboard-API. Öffnen Sie die App auf 127.0.0.1 oder https, oder fügen Sie mit Strg+V ein.",
"clipboard_write_unavailable": "Automatisches Kopieren nicht möglich. Öffnen Sie die Seite über https oder http://127.0.0.1, oder markieren Sie den Text und kopieren Sie ihn manuell.",
"oversized_body_notice": "Diese Nachricht ist zu groß, um sie hier anzuzeigen ({count} Zeichen). Kopieren Sie den vollständigen Text, um ihn woanders zu lesen oder zu bearbeiten.",
"oversized_body_copy": "Volltext kopieren",
@ -1819,7 +1819,7 @@
"failed_start_recording": "Aufnahme starten fehlgeschlagen",
"failed_start_recording_help_mediadevices": "Diese Webansicht stellt keine Mikrofon-API bereit.",
"failed_start_recording_help_web_audio": "Web Audio ist in diesem Browser nicht verfügbar.",
"failed_start_recording_help_audio_worklet": "AudioWorklet wird nicht unterstützt OPUS-Sprachnotizen benötigen es.",
"failed_start_recording_help_audio_worklet": "AudioWorklet wird nicht unterstützt. OPUS-Sprachnotizen benötigen es.",
"failed_start_recording_help_permission": "Mikrofonzugriff erlauben oder erneut versuchen, sobald eine andere App das Mikrofon freigibt.",
"remove_audio_confirm": "Sind Sie sicher, dass Sie diesen Audio-Anhang entfernen möchten?",
"failed_generate_qr": "QR-Code konnte nicht generiert werden",
@ -2140,7 +2140,7 @@
"licenses": {
"section_label": "Rechtliches",
"title": "Lizenzen Dritter",
"description": "Versionen, Autoren und SPDX- oder deklarierte Lizenzangaben zur Laufzeit. Daten stammen aus der installierten Python-Umgebung. Frontend-Daten nutzen pnpm, falls es funktioniert. Sonst werden Pakete aus node_modules gelesen (z. B. wenn pnpm licenses an der Lockfile scheitert).",
"description": "Versionen, Autoren und SPDX- oder deklarierte Lizenzangaben zur Laufzeit. Daten stammen aus der installierten Python-Umgebung. Frontend-Daten nutzen pnpm, falls es funktioniert. Sonst werden Pakete aus node_modules gelesen (z. B. Wenn pnpm licenses an der Lockfile scheitert).",
"short_description": "Versionen, Autoren und Lizenzen für Backend und Frontend.",
"search_placeholder": "Pakete, Versionen, Autoren, Lizenzen suchen...",
"generated_at": "Erstellt um {time}",
@ -2866,7 +2866,7 @@
"argos_translate": "Argos Translate",
"libretranslate": "LibreTranslate",
"api_server": "LibreTranslate API-Server",
"api_server_description": "Geben Sie die Basis-URL Ihres LibreTranslate-Servers ein (z. B. http://localhost:5000)",
"api_server_description": "Geben Sie die Basis-URL Ihres LibreTranslate-Servers ein (z. B. Http://localhost:5000)",
"api_key_optional": "LibreTranslate API-Schlüssel (optional)",
"api_key_placeholder": "Leer lassen, sofern Ihr Anbieter keinen verlangt",
"api_key_description": "Falls erforderlich, erwartet LibreTranslate dies als api_key im JSON-Übersetzungskörper und optional bei der Sprachenanfrage. Bei typischen selbst gehosteten Instanzen weglassen.",
@ -3344,14 +3344,14 @@
"micron_wasm_update_source_upload": "Lokale Datei (nicht verifiziert)",
"micron_wasm_update_active_size": "Größe: {bytes} Bytes",
"micron_wasm_update_bundled_only": "Es wird das mit der App gebündelte WASM verwendet. Es wird nichts aus dem Netz geladen, bis Sie eine der Aktionen unten nutzen.",
"micron_wasm_update_isolation_note": "Der Browser kann WebAssembly nicht vollständig von JavaScript isolieren. Diese App stellt die Micron-Konvertierung nur über eine schmale API bereit; gerendertes HTML wird weiter bereinigt. wasm_exec.js stammt immer aus dem App-Bundle, passend zur Go-Laufzeit.",
"micron_wasm_update_isolation_note": "Der Browser kann WebAssembly nicht vollständig von JavaScript isolieren. Diese App stellt die Micron-Konvertierung nur über eine schmale API bereit. Gerendertes HTML wird weiter bereinigt. Wasm_exec.js stammt immer aus dem App-Bundle, passend zur Go-Laufzeit.",
"micron_wasm_update_github_heading": "Installation aus GitHub-Release",
"micron_wasm_update_github_url_hint": "Mit „Abrufen“ lädt der MeshChat-Server von GitHub herunter (Browser bleibt same-origin für CSP). Quellpfad:",
"micron_wasm_update_fetch_github": "Abrufen und installieren",
"micron_wasm_update_upload_heading": "Installation aus Datei",
"micron_wasm_update_upload_warning": "Hochgeladenes WASM wird nicht auf Echtheit geprüft. Nur Dateien verwenden, denen Sie vertrauen.",
"micron_wasm_update_revert_bundled": "Überschreibung entfernen (gebündeltes WASM)",
"micron_wasm_update_err_empty_tag": "Release-Tag eingeben (z. B. v1.0.5).",
"micron_wasm_update_err_empty_tag": "Release-Tag eingeben (z. B. V1.0.5).",
"micron_wasm_update_err_not_wasm": "Wählen Sie eine Datei, deren Name auf .wasm endet.",
"micron_wasm_update_err_too_large": "Die Datei ist zu groß für eine Laufzeit-Überschreibung.",
"micron_wasm_update_err_too_small": "Die Datei ist zu klein für ein gültiges WASM-Modul.",
@ -3398,7 +3398,7 @@
"reduce_background_polling": "Slow background status polling",
"reduce_background_polling_desc": "Multiplies App shell poll intervals (calls, unread, app info).",
"background_poll_multiplier": "Background poll multiplier",
"background_poll_multiplier_desc": "210. Applied to App shell intervals when the option above is on.",
"background_poll_multiplier_desc": "2-10. Applied to App shell intervals when the option above is on.",
"reduce_interfaces_discovery": "Slow Interfaces page polls",
"reduce_interfaces_discovery_desc": "Uses the intervals below for stats and discovered-interface refresh.",
"interfaces_stats_poll_seconds": "Interfaces stats poll (seconds)",

File diff suppressed because it is too large Load diff

View file

@ -433,8 +433,8 @@
"map_tiles_heading": "Teselas y sin conexión",
"map_overlay_limits_heading": "Límites de superposiciones remotas",
"map_overlay_limits_desc": "Límites de protección para importaciones KMZ/KML/GeoJSON desde NomadNet y RNGit. Los valores se restringen a rangos seguros.",
"map_overlay_max_bytes": "Tamaño máx. del archivo de superposición (bytes)",
"map_overlay_max_features": "Elementos máx. por superposición",
"map_overlay_max_bytes": "Tamaño máx. Del archivo de superposición (bytes)",
"map_overlay_max_features": "Elementos máx. Por superposición",
"map_overlay_max_kmz_uncompressed_bytes": "Tamaño máx. KMZ sin comprimir (bytes)",
"map_overlay_max_sources": "Fuentes de superposición máx.",
"map_overlay_max_concurrent_jobs": "Trabajos de superposición concurrentes máx.",
@ -486,7 +486,7 @@
"copy_rpc_config": "Copiar configuración RPC",
"connected_to_shared_instance": "Este proceso de MeshChatX está conectado a una instancia externa compartida de Reticulum. Edite la configuración de esa instancia para cambiar los ajustes de compartir/RPC.",
"copy_failed": "Error al copiar al portapapeles",
"rpc_key_hidden": "Oculta — toca para mostrar",
"rpc_key_hidden": "Oculta. Toca para mostrar",
"rpc_key_show": "Mostrar clave RPC",
"rpc_key_hide": "Ocultar clave RPC",
"refresh_community_interfaces": "Actualizar desde directory.rns.recipes",
@ -1205,7 +1205,7 @@
"memory_pressure_relaxed": "Active (low host RAM)",
"memory_pressure_paths": "{count} rutas rastreadas",
"env_host_battery": "Bateria del host",
"app_battery_use": "Bat. est. MeshChatX",
"app_battery_use": "Bat. Est. MeshChatX",
"app_battery_use_hint": "Estimacion por tiempo de CPU de MeshChatX desde el inicio. No es atribucion del SO.",
"app_battery_use_warming": "Midiendo…",
"app_battery_use_rate": "~{rate}",
@ -1415,8 +1415,8 @@
"tile_connectivity_retry": "Reintentar mosaicos",
"tile_connectivity_use_offline": "Modo sin conexión",
"tile_connectivity_dismiss": "Cerrar",
"tile_failover_trying": "Falló la carga de mosaicos; probando {provider}…",
"tile_failover_offline": "Mosaicos en línea no disponibles; cambiando a modo sin conexión",
"tile_failover_trying": "Falló la carga de mosaicos. Probando {provider}…",
"tile_failover_offline": "Mosaicos en línea no disponibles. Cambiando a modo sin conexión",
"search_no_results": "No se han encontrado resultados",
"custom_tile_server_unavailable": "El servidor de baldosas personalizado no es accesible en modo offline",
"custom_nominatim_unavailable": "Nominatim servidor personalizado no es accesible en modo offline",
@ -1521,7 +1521,7 @@
"remote_overlays_kind": "Tipo de origen",
"remote_overlays_url": "URL de origen",
"remote_overlays_paths": "Rutas de archivos del repositorio (una por línea)",
"remote_overlays_ref": "Ref. de Git (rama, etiqueta o commit)",
"remote_overlays_ref": "Ref. De Git (rama, etiqueta o commit)",
"remote_overlays_refresh_interval": "Intervalo de actualización automática (segundos, 0 = desactivado)",
"remote_overlays_import": "Importar / obtener",
"remote_overlays_importing": "Obteniendo…",
@ -1593,7 +1593,7 @@
"snr": "SNR{snr}",
"stamp_cost": "Costo de sello{cost}",
"stamp_ticket_valid": "Boleto de sello saliente activo (envío instantáneo). Caduca {expires}.",
"stamp_ticket_expired": "Boleto de sello caducado; el próximo mensaje puede requerir prueba de trabajo.",
"stamp_ticket_expired": "Boleto de sello caducado. El próximo mensaje puede requerir prueba de trabajo.",
"pop_out_chat": "Apágalo.",
"open_in_split": "Abrir en vista dividida",
"select_conversation_for_pane": "Selecciona una conversación para abrirla aquí",
@ -1900,7 +1900,7 @@
"micron_wasm_update_source_upload": "Archivo local (sin verificar)",
"micron_wasm_update_active_size": "Tamaño: {bytes} bytes",
"micron_wasm_update_bundled_only": "Se usa el WASM incluido con la aplicación. No se descarga nada de la red hasta que use las acciones siguientes.",
"micron_wasm_update_isolation_note": "El navegador no puede aislar por completo WebAssembly de JavaScript. Esta aplicación solo expone la conversión Micron mediante una API limitada; el HTML generado sigue saneándose. wasm_exec.js siempre proviene del paquete de la aplicación para coincidir con el runtime de Go.",
"micron_wasm_update_isolation_note": "El navegador no puede aislar por completo WebAssembly de JavaScript. Esta aplicación solo expone la conversión Micron mediante una API limitada. El HTML generado sigue saneándose. Wasm_exec.js siempre proviene del paquete de la aplicación para coincidir con el runtime de Go.",
"micron_wasm_update_github_heading": "Instalar desde versión de GitHub",
"micron_wasm_update_github_url_hint": "Pulse Obtener para que el servidor MeshChat descargue desde GitHub (el navegador sigue en el mismo origen por la CSP). Ruta de origen:",
"micron_wasm_update_fetch_github": "Obtener e instalar",
@ -1954,7 +1954,7 @@
"reduce_background_polling": "Slow background status polling",
"reduce_background_polling_desc": "Multiplies App shell poll intervals (calls, unread, app info).",
"background_poll_multiplier": "Background poll multiplier",
"background_poll_multiplier_desc": "210. Applied to App shell intervals when the option above is on.",
"background_poll_multiplier_desc": "2-10. Applied to App shell intervals when the option above is on.",
"reduce_interfaces_discovery": "Slow Interfaces page polls",
"reduce_interfaces_discovery_desc": "Uses the intervals below for stats and discovered-interface refresh.",
"interfaces_stats_poll_seconds": "Interfaces stats poll (seconds)",
@ -3282,7 +3282,7 @@
"contact_name_optional": "Nombre de contacto (opcional)",
"contact_name_placeholder": "por ejemplo, Nodo de Campo",
"hash_or_uri": "LXMF Hash o URI",
"hash_or_uri_placeholder": "hash de 32 caracteres, lxmf://... o lxma://...",
"hash_or_uri_placeholder": "hash de 32 caracteres, lxmf://... O lxma://...",
"paste": "Pegar",
"failed_load_contacts": "No se pudieron cargar los contactos",
"invalid_contact_input": "Invalida entrada. Use a 32-char hash or lxma:// URI.",

View file

@ -21,7 +21,7 @@
"bot_stopped": "Botti pysäytetty",
"start_pending": "Käynnistetään bottia... LXMF:llä ja Reticulumilla menee hetki.",
"stop_pending": "Pysäytetään bottia",
"restart_pending": "Pysäytetään bottia... tähän voi mennä hetki.",
"restart_pending": "Pysäytetään bottia... Tähän voi mennä hetki.",
"bot_ready": "Botti on käynnissä",
"failed_to_start": "Botin käynnistys epäonnistui",
"failed_to_stop": "Botin pysäytys epäonnistui",
@ -228,7 +228,7 @@
"run_local_node": "Ylläpidä paikallista levityssolmua",
"run_local_node_description": "MeshChatX kuuluttaa ja ylläpitää solmua tämän tiivisteen kohteessa.",
"preferred_propagation_node": "Suosittu levityssolmu",
"preferred_node_placeholder": "Kohteen tiiviste, esim. a39610c89d18bb48c73e429582423c24",
"preferred_node_placeholder": "Kohteen tiiviste, esim. A39610c89d18bb48c73e429582423c24",
"fallback_node_description": "Viestit palautuvat tähän solmuun, kun suora toimitus epäonnistuu.",
"auto_select_node": "Valitse paras solmu automaattisesti",
"auto_select_node_description": "Etsi ja valitse automaattisesti lähin saatavilla oleva levityssolmu.",
@ -403,7 +403,7 @@
"csp_settings": "Sisällön turvallisuuskäytänteet (CSP)",
"csp_description": "Lisää käsin sallittuja verkkotunnuksia eri lähteille. Tätä voi käyttää karttapalveluille, boteille tai ulkoisille liitännäisille.",
"csp_extra_connect_src": "Ylimääräiset yhteyslähteet",
"csp_extra_connect_src_description": "Lisälähteet nouto-/websocket-yhteyksille (e.g. https://api.example.com).",
"csp_extra_connect_src_description": "Lisälähteet nouto-/websocket-yhteyksille (e.g. Https://api.example.com).",
"csp_extra_img_src": "Lisälähteet kuville",
"csp_extra_img_src_description": "Kuvien ja karttalaattojen lisälähteet.",
"csp_extra_frame_src": "Iframe-lisälähteet",
@ -486,7 +486,7 @@
"copy_rpc_config": "Kopioi RPC-asetukset",
"connected_to_shared_instance": "Tämä MeshChatX-prosessi on liitetty ulkoiseen jaettuun Reticulum-instanssiin. Muokkaa kyseisen instanssin asetuksia muuttaaksesi jako-/RPC-asetuksia.",
"copy_failed": "Kopiointi leikepöydälle epäonnistui",
"rpc_key_hidden": "Piilotettu — napauta näyttääksesi",
"rpc_key_hidden": "Piilotettu. Napauta näyttääksesi",
"rpc_key_show": "Näytä RPC-avain",
"rpc_key_hide": "Piilota RPC-avain",
"refresh_community_interfaces": "Päivitä lähteestä directory.rns.recipes",
@ -613,7 +613,7 @@
"title_label": "Nimike",
"title_placeholder": "Minun arkkini",
"short_name_label": "Lyhyt nimi",
"short_name_placeholder": "esim. kissat",
"short_name_placeholder": "esim. Kissat",
"description_label": "Kuvaus",
"type_label": "Tyyppi",
"type_static": "Staattinen",
@ -1415,8 +1415,8 @@
"tile_connectivity_retry": "Hae laatat uudelleen",
"tile_connectivity_use_offline": "Käytä yhteydetöntä tilaa",
"tile_connectivity_dismiss": "Hylkää",
"tile_failover_trying": "Karttalaattojen lataus epäonnistui; yritetään {provider}…",
"tile_failover_offline": "Verkossa olevat laatat eivät ole saatavilla; vaihdetaan yhteydettömään tilaan",
"tile_failover_trying": "Karttalaattojen lataus epäonnistui. Yritetään {provider}…",
"tile_failover_offline": "Verkossa olevat laatat eivät ole saatavilla. Vaihdetaan yhteydettömään tilaan",
"search_no_results": "Ei tuloksia",
"custom_tile_server_unavailable": "Mukautettu laattapalvelin ei ole saatavilla yhteydettömässä tilassa",
"custom_nominatim_unavailable": "Mukautettu Nominatim-palvelin ei ole saatavilla yhteydettömässä tilassa",
@ -1593,7 +1593,7 @@
"snr": "SNR {snr}",
"stamp_cost": "Leiman hinta {cost}",
"stamp_ticket_valid": "Lähtevien viestien merkintä on voimassa (toimitus heti). Vanhenee {expires}.",
"stamp_ticket_expired": "Leimamerkintä on vanhentunut; seuraava viesti voi vaatia PoW-työtä.",
"stamp_ticket_expired": "Leimamerkintä on vanhentunut. Seuraava viesti voi vaatia PoW-työtä.",
"pop_out_chat": "Irrota keskustelu",
"open_in_split": "Avaa jaetussa näkymässä",
"select_conversation_for_pane": "Valitse keskustelu avataksesi sen tässä",
@ -1704,7 +1704,7 @@
"folders_imported": "Kansiot tuotu",
"failed_import_folders": "Kansioiden tuonti epäonnistui",
"failed_read_clipboard": "Leikepöydän lukeminen epäonnistui",
"clipboard_read_requires_secure_context": "Leikepöytä luetaan vain suojatuilla sivuilla (https or http://127.0.0.1). http://0.0.0.0 tai muu ei-paikallinen HTTP lähde estää leikepöydän rajapinnan — avaa sovellus osoitteessa 127.0.0.1 tai käyttäen https-protokollaa, tai liitä painamalla Ctrl+V.",
"clipboard_read_requires_secure_context": "Leikepöytä luetaan vain suojatuilla sivuilla (https or http://127.0.0.1). http://0.0.0.0 tai muu ei-paikallinen HTTP lähde estää leikepöydän rajapinnan. Avaa sovellus osoitteessa 127.0.0.1 tai käyttäen https-protokollaa, tai liitä painamalla Ctrl+V.",
"clipboard_write_unavailable": "Automaattinen kopiointi epäonnistui. Avaa https-protokollalla tai osoitteessa http://127.0.0.1, tai valitse teksti ja kopioi se käsin.",
"oversized_body_notice": "Viesti on liian pitkä näytettäväksi tässä ({count} merkkiä). Kopioi koko teksti luettavaksi tai muokattavaksi muualla.",
"oversized_body_copy": "Kopioi koko teksti",
@ -1766,7 +1766,7 @@
"failed_start_recording": "tallennuksen aloitus epäonnistui",
"failed_start_recording_help_mediadevices": "Rajapintaa mikrofonin käyttöön ei ole saatavilla tässä verkkonäkymässä.",
"failed_start_recording_help_web_audio": "Web Audio ei ole saatavilla tällä selaimella.",
"failed_start_recording_help_audio_worklet": "AudioWorklet ei ole tuettu OPUS-ääniviestit vaativat sen.",
"failed_start_recording_help_audio_worklet": "AudioWorklet ei ole tuettu. OPUS-ääniviestit vaativat sen.",
"failed_start_recording_help_permission": "Salli mikrofonin käyttö, tai yritä kun toinen sovellus vapauttaa mikrofonin käytön.",
"remove_audio_confirm": "Haluatko varmasti poistaa tämän ääniliitteen?",
"failed_generate_qr": "QR-koodin luonti epäonnistui",
@ -1916,14 +1916,14 @@
"micron_wasm_update_source_upload": "Paikallinen tiedosto (todentamaton)",
"micron_wasm_update_active_size": "Koko: {bytes} tavua",
"micron_wasm_update_bundled_only": "Käytetään sovelluksen sisäänrakennettua WASMia. Verkosta ei noudeta mitään, jos et käytä alla olevia toimintoja.",
"micron_wasm_update_isolation_note": "Selain ei pysty täysin eristämään WebAssemlyä JavaScriptistä. Sovellus paljastaa Micron-muunnoksen vain ohuelti; HTML-koodi siistitään joka tapauksessa. wasm_exec.js käytetään aina sovelluspaketista, jotta se on yhtenevä Go-runtimekomponentin kanssa.",
"micron_wasm_update_isolation_note": "Selain ei pysty täysin eristämään WebAssemlyä JavaScriptistä. Sovellus paljastaa Micron-muunnoksen vain ohuelti. HTML-koodi siistitään joka tapauksessa. Wasm_exec.js käytetään aina sovelluspaketista, jotta se on yhtenevä Go-runtimekomponentin kanssa.",
"micron_wasm_update_github_heading": "Asenna GitHub-julkaisu",
"micron_wasm_update_github_url_hint": "Napauta Nouda niin MeshChat-taustapalvelin lataa GitHubista (selaimen lähde pysyy samana sisällön suojauskäytännön (CSP) vuoksi). Lähteen polku:",
"micron_wasm_update_fetch_github": "Nouda ja asenna",
"micron_wasm_update_upload_heading": "Asenna tiedostosta",
"micron_wasm_update_upload_warning": "Ladattu WASM ei ole todennettu. Käytä vain luotettuja tiedostoja.",
"micron_wasm_update_revert_bundled": "Poista ohitus (käytä sovelluspaketin WASMia)",
"micron_wasm_update_err_empty_tag": "Anna julkaisun tagi (esim. v1.0.5).",
"micron_wasm_update_err_empty_tag": "Anna julkaisun tagi (esim. V1.0.5).",
"micron_wasm_update_err_not_wasm": "Valitse tiedosto, jonka pääte on .wasm.",
"micron_wasm_update_err_too_large": "Tiedosto on liian suuri käytettäväksi ajonaikaiseen ohitukseen.",
"micron_wasm_update_err_too_small": "Tiedosto on liian pieni ollakseen kelvollinen WASM-moduuli.",
@ -1954,7 +1954,7 @@
"reduce_background_polling": "Slow background status polling",
"reduce_background_polling_desc": "Multiplies App shell poll intervals (calls, unread, app info).",
"background_poll_multiplier": "Background poll multiplier",
"background_poll_multiplier_desc": "210. Applied to App shell intervals when the option above is on.",
"background_poll_multiplier_desc": "2-10. Applied to App shell intervals when the option above is on.",
"reduce_interfaces_discovery": "Slow Interfaces page polls",
"reduce_interfaces_discovery_desc": "Uses the intervals below for stats and discovered-interface refresh.",
"interfaces_stats_poll_seconds": "Interfaces stats poll (seconds)",
@ -2239,7 +2239,7 @@
"description": "Välitä LXMF osoitteiden välillä säilyttäen vastausosoitteen.",
"add_rule": "Lisää välityssääntö",
"name": "Nimi",
"name_placeholder": "Säännön nimi (esim. kotisolmu)...",
"name_placeholder": "Säännön nimi (esim. Kotisolmu)...",
"forward_to_hash": "Välitä kohteeseen",
"destination_placeholder": "Kohteen LXMF-tiiviste...",
"source_filter": "Lähteen suodatin (valinnainen)",
@ -3042,7 +3042,7 @@
"new_message_toast": "Uusi viesti #{room}",
"host_users": "käyttäjää",
"host_announce_interval": "Ilmoitusväli (minuuttia)",
"host_announce_interval_hint": "Joka {minutes}. minuutti",
"host_announce_interval_hint": "Joka {minutes}. Minuutti",
"host_hub_settings": "Hubin asetukset",
"presence_joined": "{count} liittyi",
"presence_left": "{count} lähti",
@ -3267,7 +3267,7 @@
"argos_translate": "Argos Translate",
"libretranslate": "LibreTranslate",
"api_server": "LibreTranslate API-palvelin",
"api_server_description": "Syötä LibreTranslate-palvelimesi perus-URL (esim. https://libretranslate.com tai http://localhost:5000).",
"api_server_description": "Syötä LibreTranslate-palvelimesi perus-URL (esim. Https://libretranslate.com tai http://localhost:5000).",
"api_key_optional": "LibreTranslate API-avain (valinnainen)",
"api_key_placeholder": "Jätä tyhjäksi, ellei palveluntarjoajasi vaadi sitä",
"api_key_description": "Tarvittaessa LibreTranslate odottaa tätä api_key-parametrina JSON-käännösrungossa ja valinnaisesti kielipyynnössä. Jätä pois tyypillisissä itse isännöidyissä instansseissa.",
@ -3357,7 +3357,7 @@
"preview_greeting": "Esikatsele tervehdystä",
"stop_preview": "Lopeta esikatselu",
"answer_delay_seconds": "Vastausviive (s)",
"max_recording_seconds": "Max. tallennus (s)",
"max_recording_seconds": "Max. Tallennus (s)",
"recording_voicemail": "Tallennetaan vastaajaviestiä",
"call_status": "Puhelun tila",
"call_recording": "Puhelun tallennus",
@ -3487,7 +3487,7 @@
"contact_name_optional": "Yhteystiedon nimi (valinnainen)",
"contact_name_placeholder": "esim. Field Node",
"hash_or_uri": "LXMF-tiiviste tai URI",
"hash_or_uri_placeholder": "32-merkin tiiviste, lxmf://... tai lxma://...",
"hash_or_uri_placeholder": "32-merkin tiiviste, lxmf://... Tai lxma://...",
"paste": "Liitä",
"failed_load_contacts": "Yhteystietojen lataus epäonnistui",
"invalid_contact_input": "Virheellinen syöte. Käytä 32-merkin tiivistettä tai lxma://-URI:a.",

View file

@ -221,7 +221,7 @@
"run_local_node": "Lancer un nœud de propagation local",
"run_local_node_description": "MeshChat annoncera et maintiendra un nœud en utilisant ce hachage de destination local.",
"preferred_propagation_node": "Nœud de propagation préféré",
"preferred_node_placeholder": "Destination hash, p.ex. a39610c89d18bb48c73e429582423c24",
"preferred_node_placeholder": "Destination hash, p.ex. A39610c89d18bb48c73e429582423c24",
"fallback_node_description": "Les messages reviennent à ce nœud lorsque la livraison directe échoue.",
"auto_select_node": "Sélection automatique du meilleur noeud",
"auto_select_node_description": "Trouver et passer automatiquement au meilleur nœud de propagation disponible basé sur les sauts réseau.",
@ -433,8 +433,8 @@
"map_tiles_heading": "Tuiles et hors ligne",
"map_overlay_limits_heading": "Limites des calques distants",
"map_overlay_limits_desc": "Gardes-fous pour les imports KMZ/KML/GeoJSON depuis NomadNet et RNGit. Les valeurs sont limitées à des plages sûres.",
"map_overlay_max_bytes": "Taille max. du fichier de calque (octets)",
"map_overlay_max_features": "Entités max. par calque",
"map_overlay_max_bytes": "Taille max. Du fichier de calque (octets)",
"map_overlay_max_features": "Entités max. Par calque",
"map_overlay_max_kmz_uncompressed_bytes": "Taille max. KMZ non compressé (octets)",
"map_overlay_max_sources": "Sources de calques max.",
"map_overlay_max_concurrent_jobs": "Tâches de calque simultanées max.",
@ -486,7 +486,7 @@
"copy_rpc_config": "Copier la configuration RPC",
"connected_to_shared_instance": "Ce processus MeshChatX est attaché à une instance Reticulum partagée externe. Modifiez la configuration de cette instance pour changer les paramètres de partage/RPC.",
"copy_failed": "Échec de la copie dans le presse-papiers",
"rpc_key_hidden": "Masquée — appuyer pour afficher",
"rpc_key_hidden": "Masquée. Appuyer pour afficher",
"rpc_key_show": "Afficher la clé RPC",
"rpc_key_hide": "Masquer la clé RPC",
"refresh_community_interfaces": "Actualiser depuis directory.rns.recipes",
@ -1205,7 +1205,7 @@
"memory_pressure_relaxed": "Active (low host RAM)",
"memory_pressure_paths": "{count} chemins suivis",
"env_host_battery": "Batterie hote",
"app_battery_use": "Batt. est. MeshChatX",
"app_battery_use": "Batt. Est. MeshChatX",
"app_battery_use_hint": "Estimation a partir du temps CPU MeshChatX depuis le demarrage. Pas une attribution OS.",
"app_battery_use_warming": "Mesure…",
"app_battery_use_rate": "~{rate}",
@ -1415,8 +1415,8 @@
"tile_connectivity_retry": "Réessayer les tuiles",
"tile_connectivity_use_offline": "Mode hors ligne",
"tile_connectivity_dismiss": "Fermer",
"tile_failover_trying": "Échec des tuiles carte ; essai de {provider}…",
"tile_failover_offline": "Tuiles en ligne indisponibles ; passage en mode hors ligne",
"tile_failover_trying": "Échec des tuiles carte. Essai de {provider}…",
"tile_failover_offline": "Tuiles en ligne indisponibles. Passage en mode hors ligne",
"search_no_results": "Aucun résultat trouvé",
"custom_tile_server_unavailable": "Le serveur de tuiles personnalisé n'est pas accessible en mode hors ligne",
"custom_nominatim_unavailable": "Le serveur Nominatim personnalisé n'est pas accessible en mode hors ligne",
@ -1593,7 +1593,7 @@
"snr": "SNR{snr}",
"stamp_cost": "Coût du timbre{cost}",
"stamp_ticket_valid": "Ticket de timbre sortant actif (envoi instantané). Expire {expires}.",
"stamp_ticket_expired": "Ticket de timbre expiré ; le prochain message peut nécessiter une preuve de travail.",
"stamp_ticket_expired": "Ticket de timbre expiré. Le prochain message peut nécessiter une preuve de travail.",
"pop_out_chat": "Clavardage",
"open_in_split": "Ouvrir en vue partagée",
"select_conversation_for_pane": "Sélectionnez une conversation pour l'ouvrir ici",
@ -1704,7 +1704,7 @@
"folders_imported": "Dossiers importés",
"failed_import_folders": "Impossible d'importer des dossiers",
"failed_read_clipboard": "Impossible de lire depuis le presse-papiers",
"clipboard_read_requires_secure_context": "La lecture du presse-papiers nécessite une page sécurisée (https ou http://127.0.0.1). Avec http://0.0.0.0 lAPI Clipboard est bloquée—utilisez 127.0.0.1 ou https, ou collez avec Ctrl+V.",
"clipboard_read_requires_secure_context": "La lecture du presse-papiers nécessite une page sécurisée (https ou http://127.0.0.1). Avec http://0.0.0.0 lAPI Clipboard est bloquée. Utilisez 127.0.0.1 ou https, ou collez avec Ctrl+V.",
"clipboard_write_unavailable": "Copie automatique impossible. Utilisez https ou http://127.0.0.1, ou copiez la sélection manuellement.",
"oversized_body_notice": "Ce message est trop volumineux pour s'afficher ici ({count} caractères). Copiez le texte intégral pour le lire ou le modifier ailleurs.",
"oversized_body_copy": "Copier le texte intégral",
@ -1766,7 +1766,7 @@
"failed_start_recording": "a échoué à démarrer l'enregistrement",
"failed_start_recording_help_mediadevices": "Cette vue web n'expose pas l'API microphone.",
"failed_start_recording_help_web_audio": "Web Audio n'est pas disponible dans ce navigateur.",
"failed_start_recording_help_audio_worklet": "AudioWorklet n'est pas pris en charge — les messages vocaux OPUS en ont besoin.",
"failed_start_recording_help_audio_worklet": "AudioWorklet n'est pas pris en charge. Les messages vocaux OPUS en ont besoin.",
"failed_start_recording_help_permission": "Autorisez l'accès au microphone, ou réessayez après qu'une autre application libère le microphone.",
"remove_audio_confirm": "Voulez-vous vraiment supprimer cette pièce jointe audio ?",
"failed_generate_qr": "Impossible de générer QR",
@ -1900,14 +1900,14 @@
"micron_wasm_update_source_upload": "Fichier local (non vérifié)",
"micron_wasm_update_active_size": "Taille : {bytes} octets",
"micron_wasm_update_bundled_only": "Utilisation du WASM fourni avec lapplication. Aucun téléchargement réseau tant que vous nutilisez pas les actions ci-dessous.",
"micron_wasm_update_isolation_note": "Le navigateur ne peut pas isoler totalement WebAssembly de JavaScript. Cette application nexpose la conversion Micron que via une API restreinte ; le HTML produit reste assaini. wasm_exec.js provient toujours du bundle pour correspondre au runtime Go.",
"micron_wasm_update_isolation_note": "Le navigateur ne peut pas isoler totalement WebAssembly de JavaScript. Cette application nexpose la conversion Micron que via une API restreinte. Le HTML produit reste assaini. Wasm_exec.js provient toujours du bundle pour correspondre au runtime Go.",
"micron_wasm_update_github_heading": "Installer depuis une version GitHub",
"micron_wasm_update_github_url_hint": "Appuyez sur Récupérer pour que le serveur MeshChat télécharge depuis GitHub (navigateur same-origin pour la CSP). Chemin source :",
"micron_wasm_update_fetch_github": "Récupérer et installer",
"micron_wasm_update_upload_heading": "Installer depuis un fichier",
"micron_wasm_update_upload_warning": "Le WASM téléversé nest pas contrôlé pour lauthenticité. Nutilisez que des fichiers de confiance.",
"micron_wasm_update_revert_bundled": "Supprimer le remplacement (WASM fourni)",
"micron_wasm_update_err_empty_tag": "Saisissez une étiquette de version (par ex. v1.0.5).",
"micron_wasm_update_err_empty_tag": "Saisissez une étiquette de version (par ex. V1.0.5).",
"micron_wasm_update_err_not_wasm": "Choisissez un fichier dont le nom se termine par .wasm.",
"micron_wasm_update_err_too_large": "Ce fichier est trop volumineux pour un remplacement dexécution.",
"micron_wasm_update_err_too_small": "Ce fichier est trop petit pour être un module WASM valide.",
@ -1954,7 +1954,7 @@
"reduce_background_polling": "Slow background status polling",
"reduce_background_polling_desc": "Multiplies App shell poll intervals (calls, unread, app info).",
"background_poll_multiplier": "Background poll multiplier",
"background_poll_multiplier_desc": "210. Applied to App shell intervals when the option above is on.",
"background_poll_multiplier_desc": "2-10. Applied to App shell intervals when the option above is on.",
"reduce_interfaces_discovery": "Slow Interfaces page polls",
"reduce_interfaces_discovery_desc": "Uses the intervals below for stats and discovered-interface refresh.",
"interfaces_stats_poll_seconds": "Interfaces stats poll (seconds)",

View file

@ -221,7 +221,7 @@
"run_local_node": "Esegui un nodo di propagazione locale",
"run_local_node_description": "MeshChat annuncerà e manterrà un nodo usando questo hash di destinazione locale.",
"preferred_propagation_node": "Nodo di Propagazione Preferito",
"preferred_node_placeholder": "Hash di destinazione, es. a39610c89d18bb48c73e429582423c24",
"preferred_node_placeholder": "Hash di destinazione, es. A39610c89d18bb48c73e429582423c24",
"fallback_node_description": "I messaggi ripiegano su questo nodo ogni volta che la consegna diretta fallisce.",
"auto_select_node": "Selezione automatica del miglior nodo",
"auto_select_node_description": "Trova e passa automaticamente al miglior nodo di propagazione disponibile in base agli hop di rete.",
@ -395,7 +395,7 @@
"csp_settings": "Content Security Policy (CSP)",
"csp_description": "Aggiungi manualmente domini consentiti per varie risorse. Utile per server di mappe personalizzati, bot o integrazioni esterne.",
"csp_extra_connect_src": "Sorgenti di Connessione Extra",
"csp_extra_connect_src_description": "Sorgenti aggiuntive per connessioni fetch/websocket (es. https://api.example.com).",
"csp_extra_connect_src_description": "Sorgenti aggiuntive per connessioni fetch/websocket (es. Https://api.example.com).",
"csp_extra_img_src": "Sorgenti Immagine Extra",
"csp_extra_img_src_description": "Sorgenti aggiuntive per immagini e tile.",
"csp_extra_frame_src": "Sorgenti Frame Extra",
@ -486,7 +486,7 @@
"copy_rpc_config": "Copia configurazione RPC",
"connected_to_shared_instance": "Questo processo MeshChatX è collegato a un'istanza Reticulum condivisa esterna. Modifica la configurazione di quell'istanza per cambiare le impostazioni di condivisione/RPC.",
"copy_failed": "Copia negli appunti fallita",
"rpc_key_hidden": "Nascosta — tocca per mostrare",
"rpc_key_hidden": "Nascosta. Tocca per mostrare",
"rpc_key_show": "Mostra chiave RPC",
"rpc_key_hide": "Nascondi chiave RPC",
"refresh_community_interfaces": "Aggiorna da directory.rns.recipes",
@ -599,7 +599,7 @@
"file_too_large_video": "Gli sticker video WEBM devono essere di 256 KB o meno.",
"invalid_dimensions": "Gli sticker devono essere al massimo 512×512 pixel con un lato esattamente 512.",
"invalid_duration": "Sticker animati e video: durata massima 3 secondi.",
"invalid_fps": "Sticker animati: 3060 FPS. Video: fino a 30 FPS.",
"invalid_fps": "Sticker animati: 30-60 FPS. Video: fino a 30 FPS.",
"invalid_codec": "Gli sticker video devono usare il codec VP9.",
"invalid_audio": "Gli sticker video non devono contenere audio.",
"invalid_tgs": "Impossibile leggere l'animazione TGS.",
@ -613,7 +613,7 @@
"title_label": "Titolo",
"title_placeholder": "Il mio pacchetto",
"short_name_label": "Nome breve",
"short_name_placeholder": "es. gatti",
"short_name_placeholder": "es. Gatti",
"description_label": "Descrizione",
"type_label": "Tipo",
"type_static": "Statico",
@ -1047,7 +1047,7 @@
"contact_name_optional": "Nome contatto (opzionale)",
"contact_name_placeholder": "es. Nodo di campo",
"hash_or_uri": "Hash LXMF o URI",
"hash_or_uri_placeholder": "Hash 32 caratteri, lxmf://... o lxma://...",
"hash_or_uri_placeholder": "Hash 32 caratteri, lxmf://... O lxma://...",
"paste": "Incolla",
"failed_load_contacts": "Impossibile caricare i contatti",
"invalid_contact_input": "Input non valido. Usa un hash di 32 caratteri o URI lxma://.",
@ -1257,7 +1257,7 @@
"memory_pressure_relaxed": "Active (low host RAM)",
"memory_pressure_paths": "{count} percorsi tracciati",
"env_host_battery": "Batteria host",
"app_battery_use": "Batt. stim. MeshChatX",
"app_battery_use": "Batt. Stim. MeshChatX",
"app_battery_use_hint": "Stima dal tempo CPU di MeshChatX dall'avvio. Non e attribuzione del SO.",
"app_battery_use_warming": "Misurazione…",
"app_battery_use_rate": "~{rate}",
@ -1467,8 +1467,8 @@
"tile_connectivity_retry": "Riprova tessere",
"tile_connectivity_use_offline": "Modalità offline",
"tile_connectivity_dismiss": "Chiudi",
"tile_failover_trying": "Caricamento tessere mappa fallito; provo {provider}…",
"tile_failover_offline": "Tessere online non disponibili; passaggio alla modalità offline",
"tile_failover_trying": "Caricamento tessere mappa fallito. Provo {provider}…",
"tile_failover_offline": "Tessere online non disponibili. Passaggio alla modalità offline",
"search_no_results": "Nessun risultato trovato",
"custom_tile_server_unavailable": "Il server tile personalizzato non è accessibile in modalità offline",
"custom_nominatim_unavailable": "Il server Nominatim personalizzato non è accessibile in modalità offline",
@ -1645,7 +1645,7 @@
"snr": "SNR {snr}",
"stamp_cost": "Costo Francobollo {cost}",
"stamp_ticket_valid": "Biglietto di francobollo in uscita attivo (invio istantaneo). Scade {expires}.",
"stamp_ticket_expired": "Biglietto scaduto; il prossimo messaggio potrebbe richiedere proof-of-work.",
"stamp_ticket_expired": "Biglietto scaduto. Il prossimo messaggio potrebbe richiedere proof-of-work.",
"pop_out_chat": "Estrai chat",
"open_in_split": "Apri in vista divisa",
"select_conversation_for_pane": "Seleziona una conversazione per aprirla qui",
@ -1760,7 +1760,7 @@
"folders_imported": "Cartelle importate",
"failed_import_folders": "Impossibile importare le cartelle",
"failed_read_clipboard": "Impossibile leggere dagli appunti",
"clipboard_read_requires_secure_context": "La lettura degli appunti richiede una pagina sicura (https o http://127.0.0.1). Con http://0.0.0.0 lAPI Clipboard è bloccata—usa 127.0.0.1 o https, oppure Incolla con Ctrl+V.",
"clipboard_read_requires_secure_context": "La lettura degli appunti richiede una pagina sicura (https o http://127.0.0.1). Con http://0.0.0.0 lAPI Clipboard è bloccata. Usa 127.0.0.1 o https, oppure Incolla con Ctrl+V.",
"clipboard_write_unavailable": "Impossibile copiare automaticamente. Usa https o http://127.0.0.1, oppure copia manualmente la selezione.",
"oversized_body_notice": "Questo messaggio è troppo grande per essere mostrato qui ({count} caratteri). Copia il testo completo per leggerlo o modificarlo altrove.",
"oversized_body_copy": "Copia testo completo",
@ -1822,7 +1822,7 @@
"failed_start_recording": "impossibile avviare la registrazione",
"failed_start_recording_help_mediadevices": "Questa webview non espone l'API del microfono.",
"failed_start_recording_help_web_audio": "Web Audio non è disponibile in questo browser.",
"failed_start_recording_help_audio_worklet": "AudioWorklet non è supportato — le note vocali OPUS lo richiedono.",
"failed_start_recording_help_audio_worklet": "AudioWorklet non è supportato. Le note vocali OPUS lo richiedono.",
"failed_start_recording_help_permission": "Consenti l'accesso al microfono o riprova dopo che un'altra app rilascia il microfono.",
"remove_audio_confirm": "Sei sicuro di voler rimuovere questo allegato audio?",
"failed_generate_qr": "Impossibile generare il QR",
@ -1952,14 +1952,14 @@
"micron_wasm_update_source_upload": "File locale (non verificato)",
"micron_wasm_update_active_size": "Dimensione: {bytes} byte",
"micron_wasm_update_bundled_only": "Si usa il WASM incluso nellapp. Nulla viene scaricato dalla rete finché non usi le azioni sotto.",
"micron_wasm_update_isolation_note": "Il browser non può isolare completamente WebAssembly da JavaScript. Questa app espone la conversione Micron solo tramite unAPI ristretta; lHTML generato resta sanificato. wasm_exec.js proviene sempre dal bundle dellapp per allinearsi al runtime Go.",
"micron_wasm_update_isolation_note": "Il browser non può isolare completamente WebAssembly da JavaScript. Questa app espone la conversione Micron solo tramite unAPI ristretta. LHTML generato resta sanificato. Wasm_exec.js proviene sempre dal bundle dellapp per allinearsi al runtime Go.",
"micron_wasm_update_github_heading": "Installa da release GitHub",
"micron_wasm_update_github_url_hint": "Premi Scarica: il server MeshChat scarica da GitHub (il browser resta same-origin per la CSP). Percorso sorgente:",
"micron_wasm_update_fetch_github": "Scarica e installa",
"micron_wasm_update_upload_heading": "Installa da file",
"micron_wasm_update_upload_warning": "Il WASM caricato non è controllato per autenticità. Usa solo file di cui ti fidi.",
"micron_wasm_update_revert_bundled": "Rimuovi sostituzione (usa WASM incluso)",
"micron_wasm_update_err_empty_tag": "Inserisci un tag di release (ad es. v1.0.5).",
"micron_wasm_update_err_empty_tag": "Inserisci un tag di release (ad es. V1.0.5).",
"micron_wasm_update_err_not_wasm": "Scegli un file il cui nome termina con .wasm.",
"micron_wasm_update_err_too_large": "Il file è troppo grande per essere salvato come sostituzione a runtime.",
"micron_wasm_update_err_too_small": "Il file è troppo piccolo per essere un modulo WASM valido.",
@ -2006,7 +2006,7 @@
"reduce_background_polling": "Slow background status polling",
"reduce_background_polling_desc": "Multiplies App shell poll intervals (calls, unread, app info).",
"background_poll_multiplier": "Background poll multiplier",
"background_poll_multiplier_desc": "210. Applied to App shell intervals when the option above is on.",
"background_poll_multiplier_desc": "2-10. Applied to App shell intervals when the option above is on.",
"reduce_interfaces_discovery": "Slow Interfaces page polls",
"reduce_interfaces_discovery_desc": "Uses the intervals below for stats and discovered-interface refresh.",
"interfaces_stats_poll_seconds": "Interfaces stats poll (seconds)",
@ -2388,7 +2388,7 @@
"licenses": {
"section_label": "Note legali",
"title": "Licenze di terze parti",
"description": "Versioni, autori e licenze SPDX o dichiarate delle dipendenze a runtime. I dati provengono dall'ambiente Python installato. Per il frontend si usa pnpm se funziona. Altrimenti i pacchetti si leggono da node_modules (ad es. se pnpm licenses fallisce sul lockfile).",
"description": "Versioni, autori e licenze SPDX o dichiarate delle dipendenze a runtime. I dati provengono dall'ambiente Python installato. Per il frontend si usa pnpm se funziona. Altrimenti i pacchetti si leggono da node_modules (ad es. Se pnpm licenses fallisce sul lockfile).",
"short_description": "Versioni, autori e licenze per backend e frontend.",
"search_placeholder": "Cerca pacchetti, versioni, autori, licenze...",
"generated_at": "Generato alle {time}",
@ -3114,7 +3114,7 @@
"argos_translate": "Argos Translate",
"libretranslate": "LibreTranslate",
"api_server": "Server API LibreTranslate",
"api_server_description": "Inserisci l'URL di base del tuo server LibreTranslate (es. http://localhost:5000)",
"api_server_description": "Inserisci l'URL di base del tuo server LibreTranslate (es. Http://localhost:5000)",
"api_key_optional": "Chiave API LibreTranslate (opzionale)",
"api_key_placeholder": "Lasciare vuoto se il provider non la richiede",
"api_key_description": "Se richiesta, LibreTranslate si aspetta api_key nel corpo JSON translate e facoltativamente nella richiesta lingue. Omettere per installazioni self-hosted tipiche.",

View file

@ -395,7 +395,7 @@
"csp_settings": "Inhoudsveiligheidsbeleid (CSP)",
"csp_description": "Handmatig toegestane domeinen en bronnen toevoegen voor verschillende soorten bronnen. Dit is nuttig voor aangepaste tile servers, bots, of externe integraties.",
"csp_extra_connect_src": "Extra verbindingsbronnen",
"csp_extra_connect_src_description": "Aanvullende bronnen voor fetch/websocket-verbindingen (bv. https://api.example.com).",
"csp_extra_connect_src_description": "Aanvullende bronnen voor fetch/websocket-verbindingen (bv. Https://api.example.com).",
"csp_extra_img_src": "Extra afbeeldingsbronnen",
"csp_extra_img_src_description": "Aanvullende bronnen voor afbeeldingen en tegels.",
"csp_extra_frame_src": "Extra framebronnen",
@ -433,15 +433,15 @@
"map_tiles_heading": "Tegels en offline",
"map_overlay_limits_heading": "Limieten voor externe overlays",
"map_overlay_limits_desc": "Beschermingslimieten voor KMZ/KML/GeoJSON-imports via NomadNet en RNGit. Waarden worden begrensd tot veilige bereiken.",
"map_overlay_max_bytes": "Max. overlay-bestandsgrootte (bytes)",
"map_overlay_max_features": "Max. objecten per overlay",
"map_overlay_max_kmz_uncompressed_bytes": "Max. ongecomprimeerde KMZ-grootte (bytes)",
"map_overlay_max_sources": "Max. overlaybronnen",
"map_overlay_max_concurrent_jobs": "Max. gelijktijdige overlaytaken",
"map_overlay_max_bytes": "Max. Overlay-bestandsgrootte (bytes)",
"map_overlay_max_features": "Max. Objecten per overlay",
"map_overlay_max_kmz_uncompressed_bytes": "Max. Ongecomprimeerde KMZ-grootte (bytes)",
"map_overlay_max_sources": "Max. Overlaybronnen",
"map_overlay_max_concurrent_jobs": "Max. Gelijktijdige overlaytaken",
"map_overlay_path_timeout_seconds": "Time-out padzoeken (seconden)",
"map_overlay_transfer_timeout_seconds": "Time-out overdracht (seconden)",
"map_overlay_job_timeout_seconds": "Time-out taak (seconden)",
"map_overlay_max_retries": "Max. ophaalpogingen",
"map_overlay_max_retries": "Max. Ophaalpogingen",
"map_overlay_retry_delay_seconds": "Basisvertraging bij opnieuw proberen (seconden)",
"map_default_lat": "Standaardbreedtegraad",
"map_default_lon": "Standaardlengtegraad",
@ -486,7 +486,7 @@
"copy_rpc_config": "Kopieer RPC-configuratie",
"connected_to_shared_instance": "Dit MeshChatX-proces is gekoppeld aan een externe gedeelde Reticulum-instantie. Bewerk de configuratie van die instantie om share/RPC-instellingen te wijzigen.",
"copy_failed": "Kopiëren naar klembord mislukt",
"rpc_key_hidden": "Verborgen — tik om te tonen",
"rpc_key_hidden": "Verborgen. Tik om te tonen",
"rpc_key_show": "RPC-sleutel tonen",
"rpc_key_hide": "RPC-sleutel verbergen",
"refresh_community_interfaces": "Vernieuwen vanaf directory.rns.recipes",
@ -613,7 +613,7 @@
"title_label": "Titel",
"title_placeholder": "Mijn rugzak.",
"short_name_label": "Korte naam",
"short_name_placeholder": "bv. katten",
"short_name_placeholder": "bv. Katten",
"description_label": "Omschrijving",
"type_label": "Type",
"type_static": "Statisch",
@ -998,7 +998,7 @@
"export_all_failed": "Exporteren van identiteiten is mislukt",
"generate_fresh": "Genereer een nieuwe Reticulum identiteit.",
"display_name": "Naam tonen",
"display_name_hint": "b.v. geheim agent",
"display_name_hint": "b.v. Geheim agent",
"current": "Lopend",
"switch": "Overschakelen naar deze identiteit",
"delete": "Identiteit verwijderen",
@ -1415,8 +1415,8 @@
"tile_connectivity_retry": "Tegels opnieuw proberen",
"tile_connectivity_use_offline": "Offlinemodus",
"tile_connectivity_dismiss": "Sluiten",
"tile_failover_trying": "Kaarttegels mislukt; probeer {provider}…",
"tile_failover_offline": "Online tegels niet beschikbaar; overschakelen naar offline modus",
"tile_failover_trying": "Kaarttegels mislukt. Probeer {provider}…",
"tile_failover_offline": "Online tegels niet beschikbaar. Overschakelen naar offline modus",
"search_no_results": "Geen resultaten gevonden",
"custom_tile_server_unavailable": "Aangepaste tile-server is niet toegankelijk in offline modus",
"custom_nominatim_unavailable": "Aangepaste Nominatim-server is niet toegankelijk in offline modus",
@ -1593,7 +1593,7 @@
"snr": "SNR{snr}",
"stamp_cost": "Postzegelkosten{cost}",
"stamp_ticket_valid": "Uitgaand postzegelticket actief (direct verzenden). Verloopt {expires}.",
"stamp_ticket_expired": "Postzegelticket verlopen; het volgende bericht kan proof-of-work vereisen.",
"stamp_ticket_expired": "Postzegelticket verlopen. Het volgende bericht kan proof-of-work vereisen.",
"pop_out_chat": "Chat uitklappen",
"open_in_split": "Openen in gesplitste weergave",
"select_conversation_for_pane": "Selecteer een gesprek om het hier te openen",
@ -1704,7 +1704,7 @@
"folders_imported": "Mappen geïmporteerd",
"failed_import_folders": "Kon mappen niet importeren",
"failed_read_clipboard": "Lezen van klembord is mislukt",
"clipboard_read_requires_secure_context": "Klembord lezen vereist een beveiligde pagina (https of http://127.0.0.1). Met http://0.0.0.0 blokkeert de browser de Clipboard-API—gebruik 127.0.0.1 of https, of plak met Ctrl+V.",
"clipboard_read_requires_secure_context": "Klembord lezen vereist een beveiligde pagina (https of http://127.0.0.1). Met http://0.0.0.0 blokkeert de browser de Clipboard-API. Gebruik 127.0.0.1 of https, of plak met Ctrl+V.",
"clipboard_write_unavailable": "Automatisch kopiëren mislukt. Gebruik https of http://127.0.0.1, of kopieer handmatig.",
"oversized_body_notice": "Dit bericht is te groot om hier te tonen ({count} tekens). Kopieer de volledige tekst om die elders te lezen of te bewerken.",
"oversized_body_copy": "Volledige tekst kopiëren",
@ -1766,7 +1766,7 @@
"failed_start_recording": "kon opname niet starten",
"failed_start_recording_help_mediadevices": "Deze webweergave biedt geen microfoon-API.",
"failed_start_recording_help_web_audio": "Web Audio is niet beschikbaar in deze browser.",
"failed_start_recording_help_audio_worklet": "AudioWorklet wordt niet ondersteund OPUS-spraaknotities hebben dit nodig.",
"failed_start_recording_help_audio_worklet": "AudioWorklet wordt niet ondersteund. OPUS-spraaknotities hebben dit nodig.",
"failed_start_recording_help_permission": "Sta microfoontoegang toe of probeer opnieuw nadat een andere app de microfoon vrijgeeft.",
"remove_audio_confirm": "Weet u zeker dat u deze audiobijlage wilt verwijderen?",
"failed_generate_qr": "Kon QR niet aanmaken",
@ -1900,14 +1900,14 @@
"micron_wasm_update_source_upload": "Lokaal bestand (niet geverifieerd)",
"micron_wasm_update_active_size": "Grootte: {bytes} bytes",
"micron_wasm_update_bundled_only": "De met de app gebundelde WASM wordt gebruikt. Er wordt niets van het netwerk gehaald tot u onderstaande acties gebruikt.",
"micron_wasm_update_isolation_note": "De browser kan WebAssembly niet volledig van JavaScript isoleren. Deze app biedt Micron-conversie alleen via een beperkte API; gerenderde HTML wordt nog steeds geschoond. wasm_exec.js komt altijd uit het app-bundel om bij de Go-runtime te passen.",
"micron_wasm_update_isolation_note": "De browser kan WebAssembly niet volledig van JavaScript isoleren. Deze app biedt Micron-conversie alleen via een beperkte API. Gerenderde HTML wordt nog steeds geschoond. Wasm_exec.js komt altijd uit het app-bundel om bij de Go-runtime te passen.",
"micron_wasm_update_github_heading": "Installeren vanaf GitHub-release",
"micron_wasm_update_github_url_hint": "Druk op Ophalen zodat de MeshChat-server van GitHub downloadt (browser blijft same-origin voor CSP). Bronpad:",
"micron_wasm_update_fetch_github": "Ophalen en installeren",
"micron_wasm_update_upload_heading": "Installeren vanaf bestand",
"micron_wasm_update_upload_warning": "Geüploade WASM wordt niet op echtheid gecontroleerd. Gebruik alleen bestanden die u vertrouwt.",
"micron_wasm_update_revert_bundled": "Overschrijving verwijderen (gebundelde WASM)",
"micron_wasm_update_err_empty_tag": "Voer een releasetag in (bijv. v1.0.5).",
"micron_wasm_update_err_empty_tag": "Voer een releasetag in (bijv. V1.0.5).",
"micron_wasm_update_err_not_wasm": "Kies een bestand waarvan de naam eindigt op .wasm.",
"micron_wasm_update_err_too_large": "Dit bestand is te groot om als runtime-overschrijving op te slaan.",
"micron_wasm_update_err_too_small": "Dit bestand is te klein om een geldige WASM-module te zijn.",
@ -1954,7 +1954,7 @@
"reduce_background_polling": "Slow background status polling",
"reduce_background_polling_desc": "Multiplies App shell poll intervals (calls, unread, app info).",
"background_poll_multiplier": "Background poll multiplier",
"background_poll_multiplier_desc": "210. Applied to App shell intervals when the option above is on.",
"background_poll_multiplier_desc": "2-10. Applied to App shell intervals when the option above is on.",
"reduce_interfaces_discovery": "Slow Interfaces page polls",
"reduce_interfaces_discovery_desc": "Uses the intervals below for stats and discovered-interface refresh.",
"interfaces_stats_poll_seconds": "Interfaces stats poll (seconds)",
@ -2044,7 +2044,7 @@
"batch": "Lot",
"loading_status": "Laden status",
"failed_load": "Kon netwerkgegevens niet laden",
"max_hops_filter": "Max. hop",
"max_hops_filter": "Max. Hop",
"show_disabled_interfaces": "Offline interfaces tonen",
"show_discovered_interfaces": "Ontdekte interfaces tonen",
"refresh": "Refresh",
@ -2336,7 +2336,7 @@
"licenses": {
"section_label": "Juridisch",
"title": "Vergunningen van derden",
"description": "Runtime afhankelijkheid versies, auteurs, en SPDX of verklaarde licentie strings. Gegevens worden verzameld uit de geïnstalleerde Python omgeving. Frontend data maakt gebruik van pnpm wanneer het werkt. Anders worden pakketten gelezen van node modules (bijv. wanneer pnpm-licenties niet werken op het slotbestand).",
"description": "Runtime afhankelijkheid versies, auteurs, en SPDX of verklaarde licentie strings. Gegevens worden verzameld uit de geïnstalleerde Python omgeving. Frontend data maakt gebruik van pnpm wanneer het werkt. Anders worden pakketten gelezen van node modules (bijv. Wanneer pnpm-licenties niet werken op het slotbestand).",
"short_description": "Afhankelijkheid versies, auteurs, en licenties voor backend en frontend.",
"search_placeholder": "Zoekpakketten, versies, auteurs, licenties...",
"generated_at": "Gegenereerd op{time}",
@ -3062,7 +3062,7 @@
"argos_translate": "Argos vertalen",
"libretranslate": "LibreVertalen",
"api_server": "LibreVertaal API-server",
"api_server_description": "Voer de basis-URL in van uw LibreTranslate-server (bijv. http://localhost:5000)",
"api_server_description": "Voer de basis-URL in van uw LibreTranslate-server (bijv. Http://localhost:5000)",
"api_key_optional": "LibreTranslate API-sleutel (optioneel)",
"api_key_placeholder": "Leeg laten tenzij uw provider er een vereist",
"api_key_description": "Indien vereist verwacht LibreTranslate dit als api_key in de JSON-vertaalbody en optioneel bij de talenrequest. Weglaten voor typische zelfgehoste installaties.",
@ -3152,7 +3152,7 @@
"preview_greeting": "Voorbeeldgroet",
"stop_preview": "Voorbeeld stoppen",
"answer_delay_seconds": "Antwoord vertraging (en)",
"max_recording_seconds": "Max. opname (s)",
"max_recording_seconds": "Max. Opname (s)",
"recording_voicemail": "Voicemail opnemen",
"call_status": "Oproepstatus",
"call_recording": "Oproeprecorder",
@ -3280,7 +3280,7 @@
"load_more": "Meer laden",
"add_contact": "Contact toevoegen",
"contact_name_optional": "Contactnaam (facultatief)",
"contact_name_placeholder": "b.v. veldknooppunt",
"contact_name_placeholder": "b.v. Veldknooppunt",
"hash_or_uri": "LXMF Hash of URI",
"hash_or_uri_placeholder": "32-char hash, lxmf://..., of lxma://...",
"paste": "Plakken",

View file

@ -336,7 +336,7 @@
"loading_overlay_kicker": "Подождите",
"loading_overlay_title": "Смена профиля",
"loading_overlay_subtitle": "Загрузка чатов и настроек. Обычно это занимает несколько секунд.",
"emergency_mode_active": "Аварийный режим активен — используется база данных в оперативной памяти и ограниченные службы.",
"emergency_mode_active": "Аварийный режим активен. Используется база данных в оперативной памяти и ограниченные службы.",
"backend_disconnected": "Нет соединения с сервером",
"backend_process_stopped": "Сервер Reticulum остановлен",
"backend_reconnected": "Соединение с сервером восстановлено",
@ -356,9 +356,9 @@
"announce_store_lxst": "LXST телефония (lxst.telephony)",
"announce_store_nomad": "Узлы NomadNet (nomadnetwork.node)",
"announce_store_prop": "Узлы рассылки (lxmf.propagation)",
"announce_max_stored_heading": "Макс. в базе на аспект",
"announce_max_stored_heading": "Макс. В базе на аспект",
"announce_fetch_limit_heading": "Размер страницы по умолчанию (API)",
"announce_search_max_fetch": "Макс. объявлений для поиска",
"announce_search_max_fetch": "Макс. Объявлений для поиска",
"announce_search_max_fetch_hint": "Максимум строк из БД при текстовом поиске (на запрос).",
"discovered_interfaces_max_return": "Лимит обнаруженных интерфейсов",
"discovered_interfaces_max_return_hint": "Максимум записей об обнаруженных и активных интерфейсах в интерфейсе.",
@ -433,15 +433,15 @@
"map_tiles_heading": "Тайлы и офлайн",
"map_overlay_limits_heading": "Лимиты удалённых оверлеев",
"map_overlay_limits_desc": "Ограничения для импорта KMZ/KML/GeoJSON из NomadNet и RNGit. Значения ограничиваются безопасным диапазоном.",
"map_overlay_max_bytes": "Макс. размер файла оверлея (байты)",
"map_overlay_max_features": "Макс. число объектов в оверлее",
"map_overlay_max_kmz_uncompressed_bytes": "Макс. несжатый размер KMZ (байты)",
"map_overlay_max_sources": "Макс. число источников оверлеев",
"map_overlay_max_concurrent_jobs": "Макс. одновременных заданий оверлея",
"map_overlay_max_bytes": "Макс. Размер файла оверлея (байты)",
"map_overlay_max_features": "Макс. Число объектов в оверлее",
"map_overlay_max_kmz_uncompressed_bytes": "Макс. Несжатый размер KMZ (байты)",
"map_overlay_max_sources": "Макс. Число источников оверлеев",
"map_overlay_max_concurrent_jobs": "Макс. Одновременных заданий оверлея",
"map_overlay_path_timeout_seconds": "Таймаут поиска пути (секунды)",
"map_overlay_transfer_timeout_seconds": "Таймаут передачи (секунды)",
"map_overlay_job_timeout_seconds": "Таймаут задания (секунды)",
"map_overlay_max_retries": "Макс. число повторов загрузки",
"map_overlay_max_retries": "Макс. Число повторов загрузки",
"map_overlay_retry_delay_seconds": "Базовая задержка повтора (секунды)",
"map_default_lat": "Широта по умолчанию",
"map_default_lon": "Долгота по умолчанию",
@ -486,7 +486,7 @@
"copy_rpc_config": "Копировать конфигурацию RPC",
"connected_to_shared_instance": "Этот процесс MeshChatX подключен к внешнему общему экземпляру Reticulum. Отредактируйте конфигурацию этого экземпляра, чтобы изменить настройки share/RPC.",
"copy_failed": "Не удалось скопировать в буфер обмена",
"rpc_key_hidden": "Скрыт — нажмите, чтобы показать",
"rpc_key_hidden": "Скрыт. Нажмите, чтобы показать",
"rpc_key_show": "Показать RPC-ключ",
"rpc_key_hide": "Скрыть RPC-ключ",
"refresh_community_interfaces": "Обновить из directory.rns.recipes",
@ -594,12 +594,12 @@
"format_video": "Видео",
"format_legacy": "Устаревший",
"errors": {
"file_too_large_static": "Статичные стикеры — не больше 512 КБ.",
"file_too_large_animated": "Анимированные TGS — не больше 64 КБ.",
"file_too_large_video": "Видео WEBM — не больше 256 КБ.",
"file_too_large_static": "Статичные стикеры. Не больше 512 КБ.",
"file_too_large_animated": "Анимированные TGS. Не больше 64 КБ.",
"file_too_large_video": "Видео WEBM. Не больше 256 КБ.",
"invalid_dimensions": "Стикеры не больше 512×512 пикселей, одна сторона ровно 512.",
"invalid_duration": "Анимированные и видео — не длиннее 3 секунд.",
"invalid_fps": "Анимация: 3060 к/с, видео — до 30 к/с.",
"invalid_duration": "Анимированные и видео. Не длиннее 3 секунд.",
"invalid_fps": "Анимация: 30-60 к/с, видео. До 30 к/с.",
"invalid_codec": "Видеостикеры должны использовать кодек VP9.",
"invalid_audio": "В видеостикерах не должно быть звуковой дорожки.",
"invalid_tgs": "Не удалось прочитать анимацию TGS.",
@ -613,7 +613,7 @@
"title_label": "Название",
"title_placeholder": "Мой набор",
"short_name_label": "Краткое имя",
"short_name_placeholder": "напр. коты",
"short_name_placeholder": "напр. Коты",
"description_label": "Описание",
"type_label": "Тип",
"type_static": "Статичные",
@ -1047,7 +1047,7 @@
"contact_name_optional": "Имя контакта (необязательно)",
"contact_name_placeholder": "например, Полевой узел",
"hash_or_uri": "LXMF-хэш или URI",
"hash_or_uri_placeholder": "32-символьный хэш, lxmf://... или lxma://...",
"hash_or_uri_placeholder": "32-символьный хэш, lxmf://... Или lxma://...",
"paste": "Вставить",
"failed_load_contacts": "Не удалось загрузить контакты",
"invalid_contact_input": "Недопустимый ввод. Используйте 32-символьный хэш или URI lxma://.",
@ -1257,12 +1257,12 @@
"memory_pressure_relaxed": "Active (low host RAM)",
"memory_pressure_paths": "{count} путей отслеживается",
"env_host_battery": "Батарея хоста",
"app_battery_use": "Оц. батарея MeshChatX",
"app_battery_use": "Оц. Батарея MeshChatX",
"app_battery_use_hint": "Оценка по CPU-времени MeshChatX с запуска. Не системная атрибуция.",
"app_battery_use_warming": "Измерение…",
"app_battery_use_rate": "~{rate}",
"app_battery_use_with_intensity": "~{rate} ({intensity})",
"app_battery_share": "Оц. доля CPU",
"app_battery_share": "Оц. Доля CPU",
"app_battery_share_value": "{percent}% устройства",
"app_battery_intensity_low": "низкая",
"app_battery_intensity_moderate": "средняя",
@ -1321,16 +1321,16 @@
"discovery_list_refresh_failed": "Не удалось обновить список обнаруженных интерфейсов.",
"discovery_default_bootstrap_only": "По умолчанию только bootstrap для нового исходящего TCP",
"discovery_default_bootstrap_only_hint": "Новые TCP-клиент и backbone-коннектор получают bootstrap_only, чтобы Reticulum отключил их при достижении autoconnect_discovered_interfaces.",
"discovery_default_bootstrap_docs_link": "См. раздел о bootstrap-подключении Reticulum.",
"discovery_default_bootstrap_docs_link": "См. Раздел о bootstrap-подключении Reticulum.",
"backbone_transport_identity_label": "Идентичность транспорта (необязательно)",
"backbone_transport_identity_placeholder": "e53433e51cde34c42a3245ba3fe1ad69",
"backbone_transport_identity_hint": "Как в примерах удалённого backbone Reticulum только с remote и target_port. Указывайте хеш, если это задал оператор или каталог.",
"loopback_local_title": "Локальный / loopback",
"loopback_local_body": "Reticulum использует общую инстанцию внутри. Чтобы связаться с другим процессом RNS на этом хосте, используйте TCP-клиент на 127.0.0.1 с портом инстанции или внешний модуль интерфейса.",
"loopback_local_docs_hint": "См. главу Interfaces о поддерживаемых типах.",
"loopback_local_docs_hint": "См. Главу Interfaces о поддерживаемых типах.",
"loopback_local_docs_link": "Открыть встроенное руководство Reticulum",
"custom_external_intro": "Типы вроде WeaveInterface загружаются, если Reticulum находит подходящий файл модуля (TypeName.py) в interfacepath с interface_class (внешний загрузчик RNS). Поля JSON попадают в секцию interface в вашем конфиге.",
"custom_external_install_intro": "В Android папка Android/data часто скрыта в приложении «Файлы». Используйте «Установить модуль», чтобы скопировать TypeName.py в interfacepath этого приложения через системный выбор файлов (Загрузки, Диск, Bluetooth и т. д.).",
"custom_external_install_intro": "В Android папка Android/data часто скрыта в приложении «Файлы». Используйте «Установить модуль», чтобы скопировать TypeName.py в interfacepath этого приложения через системный выбор файлов (Загрузки, Диск, Bluetooth и т. Д.).",
"custom_external_interfacepath_label": "Активный interfacepath",
"custom_external_install_button": "Установить модуль (.py)",
"custom_external_install_overwrite": "Перезаписать, если есть",
@ -1342,12 +1342,12 @@
"custom_external_module_delete_failed": "Не удалось удалить модуль интерфейса",
"custom_external_type_label": "Имя типа интерфейса",
"custom_external_type_placeholder": "WeaveInterface",
"custom_external_json_label": "Доп. параметры (JSON-объект)",
"custom_external_json_label": "Доп. Параметры (JSON-объект)",
"custom_external_json_placeholder": "\"listen_ip\": \"0.0.0.0\", \"listen_port\": 4242",
"custom_external_docs_hint": "См. руководство Interfaces про встроенные типы и внешние модули.",
"custom_external_docs_hint": "См. Руководство Interfaces про встроенные типы и внешние модули.",
"custom_external_docs_link": "Открыть встроенное руководство Reticulum",
"custom_external_type_required": "Укажите имя типа интерфейса Reticulum.",
"custom_external_json_invalid": "Некорректный JSON для доп. параметров.",
"custom_external_json_invalid": "Некорректный JSON для доп. Параметров.",
"failed_save_discovery": "Не удалось сохранить настройки обнаружения",
"no_interfaces_found_config": "В выбранном файле конфигурации интерфейсы не найдены",
"failed_parse_config": "Не удалось разобрать файл конфигурации",
@ -1391,7 +1391,7 @@
"listen_ip_required": "Укажите IP для прослушивания.",
"kernel_iface_picker_title": "Интерфейсы на этом узле",
"kernel_iface_loading": "Загрузка…",
"kernel_iface_picker_help": "Поле «устройство» необязательно: одно имя интерфейса ядра или пусто — привязка только по Listen IP. Нажмите строку, чтобы подставить имя.",
"kernel_iface_picker_help": "Поле «устройство» необязательно: одно имя интерфейса ядра или пусто. Привязка только по Listen IP. Нажмите строку, чтобы подставить имя.",
"auto_iface_ifname_chips_hint": "Интерфейсы этого узла: нажмите, чтобы добавить или убрать имя в поле выше.",
"i2p_requirements_title": "Правила интерфейса I2P",
"i2p_requirements_body": "Допускается только один интерфейс I2P. Сначала включите режим транспорта в настройках, затем добавьте I2P последним. Не импортируйте I2P из файла конфигурации и не редактируйте его в сыром редакторе. Изменения, оставляющие I2P не последним, автоматически исправляются при сохранении и запуске.",
@ -1438,8 +1438,8 @@
"set_as_default": "Установить как вид по умолчанию",
"export_area": "Экспорт области",
"export_instructions": "Выделите область на карте для экспорта.",
"min_zoom": "Мин. масштаб",
"max_zoom": "Макс. масштаб",
"min_zoom": "Мин. Масштаб",
"max_zoom": "Макс. Масштаб",
"tile_count": "Оценка тайлов",
"start_export": "Начать экспорт",
"exporting": "Экспорт карты...",
@ -1467,8 +1467,8 @@
"tile_connectivity_retry": "Повторить загрузку тайлов",
"tile_connectivity_use_offline": "Офлайн-режим",
"tile_connectivity_dismiss": "Закрыть",
"tile_failover_trying": "Не удалось загрузить тайлы карты; пробую {provider}…",
"tile_failover_offline": "Онлайн-тайлы недоступны; переключение в автономный режим",
"tile_failover_trying": "Не удалось загрузить тайлы карты. Пробую {provider}…",
"tile_failover_offline": "Онлайн-тайлы недоступны. Переключение в автономный режим",
"search_no_results": "Результаты не найдены",
"custom_tile_server_unavailable": "Пользовательский сервер тайлов недоступен в офлайн-режиме",
"custom_nominatim_unavailable": "Пользовательский сервер Nominatim недоступен в офлайн-режиме",
@ -1645,7 +1645,7 @@
"snr": "SNR {snr}",
"stamp_cost": "Стоимость штампа {cost}",
"stamp_ticket_valid": "Активный исходящий билет штампа (мгновенная отправка). Истекает {expires}.",
"stamp_ticket_expired": "Билет штампа истёк; следующее сообщение может потребовать proof-of-work.",
"stamp_ticket_expired": "Билет штампа истёк. Следующее сообщение может потребовать proof-of-work.",
"pop_out_chat": "Открыть в отдельном окне",
"open_in_split": "Открыть в разделённом виде",
"select_conversation_for_pane": "Выберите беседу, чтобы открыть её здесь",
@ -1760,7 +1760,7 @@
"folders_imported": "Папки импортированы",
"failed_import_folders": "Не удалось импортировать папки",
"failed_read_clipboard": "Не удалось прочитать из буфера обмена",
"clipboard_read_requires_secure_context": "Для чтения буфера обмена требуется безопасная страница (https или http://127.0.0.1). Использование http://0.0.0.0 или другого нелокального HTTP-источника блокирует API буфера обменаоткройте приложение на 127.0.0.1 или https, либо вставьте с помощью Ctrl+V.",
"clipboard_read_requires_secure_context": "Для чтения буфера обмена требуется безопасная страница (https или http://127.0.0.1). Использование http://0.0.0.0 или другого нелокального HTTP-источника блокирует API буфера обмена. Откройте приложение на 127.0.0.1 или https, либо вставьте с помощью Ctrl+V.",
"clipboard_write_unavailable": "Не удалось скопировать автоматически. Откройте на https или http://127.0.0.1, либо выделите текст и скопируйте вручную.",
"oversized_body_notice": "Сообщение слишком длинное для отображения здесь ({count} символов). Скопируйте полный текст, чтобы прочитать или изменить его в другом приложении.",
"oversized_body_copy": "Копировать полный текст",
@ -1819,7 +1819,7 @@
"failed_start_recording": "Не удалось начать запись",
"failed_start_recording_help_mediadevices": "Этот веб-интерфейс не предоставляет доступ к микрофону.",
"failed_start_recording_help_web_audio": "Web Audio недоступен в этом браузере.",
"failed_start_recording_help_audio_worklet": "AudioWorklet не поддерживается — для голосовых заметок OPUS требуется его поддержка.",
"failed_start_recording_help_audio_worklet": "AudioWorklet не поддерживается. Для голосовых заметок OPUS требуется его поддержка.",
"failed_start_recording_help_permission": "Разрешите доступ к микрофону или повторите попытку после того, как другое приложение освободит микрофон.",
"remove_audio_confirm": "Вы уверены, что хотите удалить это аудиовложение?",
"failed_generate_qr": "Не удалось сгенерировать QR-код",
@ -2420,7 +2420,7 @@
"eeprom_console_hint": "Дампы EEPROM отображаются в консоли инструментов разработчика.",
"configure_bluetooth": "Настройка Bluetooth (опционально)",
"bluetooth_info_1": "Bluetooth поддерживается не на всех устройствах.",
"bluetooth_info_2": "Некоторые устройства используют Bluetooth Classic, а некоторые BLE (Bluetooth Low Energy).",
"bluetooth_info_2": "Некоторые устройства используют Bluetooth Classic, а некоторые. BLE (Bluetooth Low Energy).",
"bluetooth_info_3": "Переведите RNode в режим сопряжения Bluetooth, затем подключитесь к нему в настройках Bluetooth Android.",
"bluetooth_info_4": "После инициирования запроса на сопряжение из Android, PIN-код должен отобразиться на экране RNode.",
"bluetooth_info_5": "В Sideband вам нужно включить 'Подключиться через Bluetooth' в Оборудование → RNode.",
@ -2956,7 +2956,7 @@
"preview_greeting": "Предпросмотр приветствия",
"stop_preview": "Остановить предпросмотр",
"answer_delay_seconds": "Задержка ответа (с)",
"max_recording_seconds": "Макс. время записи (с)",
"max_recording_seconds": "Макс. Время записи (с)",
"recording_voicemail": "Запись голосового сообщения",
"call_status": "Статус звонка",
"call_recording": "Запись звонков",
@ -3344,7 +3344,7 @@
"micron_wasm_update_source_upload": "Локальный файл (без проверки подлинности)",
"micron_wasm_update_active_size": "Размер: {bytes} байт",
"micron_wasm_update_bundled_only": "Используется WASM, поставляемый с приложением. Сеть не запрашивается, пока вы не выполните действия ниже.",
"micron_wasm_update_isolation_note": "Браузер не может полностью изолировать WebAssembly от JavaScript. Приложение выставляет преобразование Micron только через узкий API; HTML по-прежнему очищается. wasm_exec.js всегда берётся из пакета приложения для соответствия среде Go.",
"micron_wasm_update_isolation_note": "Браузер не может полностью изолировать WebAssembly от JavaScript. Приложение выставляет преобразование Micron только через узкий API. HTML по-прежнему очищается. Wasm_exec.js всегда берётся из пакета приложения для соответствия среде Go.",
"micron_wasm_update_github_heading": "Установка из релиза GitHub",
"micron_wasm_update_github_url_hint": "Нажмите «Загрузить», чтобы сервер MeshChat скачал с GitHub (браузер остаётся same-origin для CSP). Путь источника:",
"micron_wasm_update_fetch_github": "Загрузить и установить",
@ -3398,7 +3398,7 @@
"reduce_background_polling": "Slow background status polling",
"reduce_background_polling_desc": "Multiplies App shell poll intervals (calls, unread, app info).",
"background_poll_multiplier": "Background poll multiplier",
"background_poll_multiplier_desc": "210. Applied to App shell intervals when the option above is on.",
"background_poll_multiplier_desc": "2-10. Applied to App shell intervals when the option above is on.",
"reduce_interfaces_discovery": "Slow Interfaces page polls",
"reduce_interfaces_discovery_desc": "Uses the intervals below for stats and discovered-interface refresh.",
"interfaces_stats_poll_seconds": "Interfaces stats poll (seconds)",
@ -3488,7 +3488,7 @@
"batch": "Пакет",
"loading_status": "Статус загрузки",
"failed_load": "Не удалось загрузить данные сети",
"max_hops_filter": "Макс. хопов",
"max_hops_filter": "Макс. Хопов",
"show_disabled_interfaces": "Показать отключенные интерфейсы",
"show_discovered_interfaces": "Показать обнаруженные интерфейсы",
"refresh": "Refresh",

View file

@ -486,7 +486,7 @@
"copy_rpc_config": "复制RPC配置",
"connected_to_shared_instance": "此MeshChatX进程已附加到外部共享的Reticulum实例。编辑该实例的配置以更改共享/RPC设置。",
"copy_failed": "复制到剪贴板失败",
"rpc_key_hidden": "已隐藏点按显示",
"rpc_key_hidden": "已隐藏点按显示",
"rpc_key_show": "显示 RPC 密钥",
"rpc_key_hide": "隐藏 RPC 密钥",
"refresh_community_interfaces": "从 directory.rns.recipes 刷新",
@ -1704,7 +1704,7 @@
"folders_imported": "文件夹已导入",
"failed_import_folders": "导入文件夹失败",
"failed_read_clipboard": "从剪贴板读取失败",
"clipboard_read_requires_secure_context": "读取剪贴板需要安全页面https 或 http://127.0.0.1)。使用 http://0.0.0.0 等非本地 HTTP 地址会阻止剪贴板 API请改用 127.0.0.1 或 https或使用 Ctrl+V 粘贴。",
"clipboard_read_requires_secure_context": "读取剪贴板需要安全页面https 或 http://127.0.0.1)。使用 http://0.0.0.0 等非本地 HTTP 地址会阻止剪贴板 API请改用 127.0.0.1 或 https或使用 Ctrl+V 粘贴。",
"clipboard_write_unavailable": "无法自动复制。请使用 https 或 http://127.0.0.1,或手动选择文本复制。",
"oversized_body_notice": "此消息过长,无法在此显示({count} 个字符)。请复制全文以便在其他应用中阅读或编辑。",
"oversized_body_copy": "复制全文",
@ -1766,7 +1766,7 @@
"failed_start_recording": "无法开始录制",
"failed_start_recording_help_mediadevices": "此 WebView 未提供麦克风 API。",
"failed_start_recording_help_web_audio": "此浏览器不支持 Web Audio。",
"failed_start_recording_help_audio_worklet": "不支持 AudioWorkletOPUS 语音留言需要它。",
"failed_start_recording_help_audio_worklet": "不支持 AudioWorkletOPUS 语音留言需要它。",
"failed_start_recording_help_permission": "请允许麦克风权限,或在其他应用释放麦克风后重试。",
"remove_audio_confirm": "您确定要删除此音频附件吗?",
"failed_generate_qr": "生成二维码失败",
@ -1954,7 +1954,7 @@
"reduce_background_polling": "Slow background status polling",
"reduce_background_polling_desc": "Multiplies App shell poll intervals (calls, unread, app info).",
"background_poll_multiplier": "Background poll multiplier",
"background_poll_multiplier_desc": "210. Applied to App shell intervals when the option above is on.",
"background_poll_multiplier_desc": "2-10. Applied to App shell intervals when the option above is on.",
"reduce_interfaces_discovery": "Slow Interfaces page polls",
"reduce_interfaces_discovery_desc": "Uses the intervals below for stats and discovered-interface refresh.",
"interfaces_stats_poll_seconds": "Interfaces stats poll (seconds)",
@ -2578,7 +2578,7 @@
"enter_dfu_mode": "输入 DFU 模式",
"entering_dfu_mode": "正在输入 DFU 模式...",
"find_device_issue": "找不到你的装置吗? 打开一个问题",
"select_firmware": "2. 选择要闪烁的固件 (. zip)",
"select_firmware": "2. 选择要闪烁的固件 (. Zip)",
"flash_now": "现在闪光",
"flashing": "闪光:{percentage}%",
"flashing_file_progress": "文件{current}/{total}:{percentage}%",

View file

@ -121,7 +121,7 @@ export const MESHCHAT_THEME_VARIABLES_DARK = {
};
/**
* Tailwind semantic colors (`sem-*` in class names) `@theme` in style.css mirrors these keys; same --mc-* variables as global CSS.
* Tailwind semantic colors (`sem-*` in class names). `@theme` in style.css mirrors these keys. Same --mc-* variables as global CSS.
* Keep keys in sync with usages in style.css and Vue (e.g. bg-sem-canvas).
*/
export function tailwindSemanticColorExtend() {

View file

@ -115,7 +115,7 @@ def test_jni_libs_synced_for_all_abis():
for abi in ("arm64-v8a", "armeabi-v7a", "x86_64"):
lib = jni / abi / "libcodec2.so"
if not lib.is_file():
pytest.skip(f"missing jniLibs {lib} not an Android build")
pytest.skip(f"missing jniLibs {lib}: not an Android build")
assert lib.stat().st_size > 100_000

View file

@ -60,7 +60,7 @@ class TestBenchmarkStats(unittest.TestCase):
self.assertIn("noise floor", reason)
def test_should_alert_skips_tiny_abs_delta(self):
# 3x ratio but only +0.4 ms absolute not actionable
# 3x ratio but only +0.4 ms absolute: not actionable
alert, reason = should_alert_regression(0.6, 0.2, noise_floor_ms=0.1)
self.assertFalse(alert)
self.assertIn("abs delta", reason)
@ -72,7 +72,7 @@ class TestBenchmarkStats(unittest.TestCase):
self.assertIn("slower", reason)
def test_should_alert_within_adaptive_threshold(self):
# 1.8x on a 10 ms baseline adaptive threshold is 2.0x
# 1.8x on a 10 ms baseline: adaptive threshold is 2.0x
alert, reason = should_alert_regression(18.0, 10.0)
self.assertFalse(alert)
self.assertIn("within adaptive", reason)

View file

@ -190,7 +190,7 @@ class TestConfigDAOFuzzing:
# ===================================================================
# MiscDAO spam keywords, notifications, keyboard shortcuts
# MiscDAO: spam keywords, notifications, keyboard shortcuts
# ===================================================================
@ -490,7 +490,7 @@ class TestMapDrawingsDAOFuzzing:
# ===================================================================
# MessageDAO folders
# MessageDAO: folders
# ===================================================================
@ -527,7 +527,7 @@ class TestMessageDAOFoldersFuzzing:
# ===================================================================
# MessageHandler search
# MessageHandler: search
# ===================================================================
@ -597,7 +597,7 @@ class TestMessageHandlerFuzzing:
# ===================================================================
# _safe_href URL sanitization
# _safe_href: URL sanitization
# ===================================================================

View file

@ -26,7 +26,7 @@ def test_flatten_pnpm_licenses_json_maps_and_sorts():
],
"Apache-2.0": [
{"name": "alpha-pkg", "versions": ["1.0.0"], "author": "Alice"},
{"name": "no-version", "versions": [], "author": ""},
{"name": "no-version", "versions": [], "author": "-"},
],
}
rows = _flatten_pnpm_licenses_json(data)

View file

@ -230,11 +230,11 @@ class TestPerformanceHotPaths(unittest.TestCase):
print("--- Seeding complete ---\n")
# ===================================================================
# ANNOUNCES load, search, count
# ANNOUNCES: load, search, count
# ===================================================================
def test_announce_load_filtered_latency(self):
"""Load announces filtered by aspect with pagination the NomadNet browser default view."""
"""Load announces filtered by aspect with pagination: the NomadNet browser default view."""
print("\n[Announce] Filtered load (aspect + pagination):")
durations = []
offsets = [0, 100, 500, 1000, 2000]
@ -275,7 +275,7 @@ class TestPerformanceHotPaths(unittest.TestCase):
self.assertLess(stats["p95"], 150, "Announce search p95 > 150ms")
def test_announce_search_with_blocked(self):
"""Search with a block-list simulates real NomadNet browser filtering."""
"""Search with a block-list: simulates real NomadNet browser filtering."""
print("\n[Announce] Search with blocked list:")
blocked = [secrets.token_hex(16) for _ in range(50)]
durations = []
@ -312,7 +312,7 @@ class TestPerformanceHotPaths(unittest.TestCase):
# ===================================================================
def test_favourites_load_latency(self):
"""Load all favourites typically displayed in sidebar."""
"""Load all favourites: typically displayed in sidebar."""
print("\n[Favourites] Load all:")
durations = []
for _ in range(50):
@ -340,11 +340,11 @@ class TestPerformanceHotPaths(unittest.TestCase):
self.assertGreater(stats["ops"], 500, "Favourite upsert < 500 ops/s")
# ===================================================================
# CONVERSATIONS load, search
# CONVERSATIONS: load, search
# ===================================================================
def test_conversations_load_latency(self):
"""Load conversation list the main messages sidebar query."""
"""Load conversation list: the main messages sidebar query."""
print("\n[Conversations] Load list (with JOINs):")
durations = []
for _ in range(20):
@ -360,7 +360,7 @@ class TestPerformanceHotPaths(unittest.TestCase):
self.assertLess(stats["p95"], 200, "Conversation list p95 > 200ms")
def test_conversations_search_latency(self):
"""Search conversations LIKE across titles, content, peer hashes."""
"""Search conversations: LIKE across titles, content, peer hashes."""
print("\n[Conversations] Search:")
terms = [
"Message title 5",
@ -399,7 +399,7 @@ class TestPerformanceHotPaths(unittest.TestCase):
self.assertLess(stats["p95"], 300, "Paginated conversations p95 > 300ms")
# ===================================================================
# MESSAGES load, search, upsert (drafts)
# MESSAGES: load, search, upsert (drafts)
# ===================================================================
def test_message_load_latency(self):
@ -422,7 +422,7 @@ class TestPerformanceHotPaths(unittest.TestCase):
self.assertLess(stats["p99"], 50, "Message load p99 > 50ms")
def test_message_search_latency(self):
"""Search messages across all conversations the global search."""
"""Search messages across all conversations: the global search."""
print("\n[Messages] Global search:")
terms = [
"Message title 100",
@ -443,7 +443,7 @@ class TestPerformanceHotPaths(unittest.TestCase):
self.assertLess(stats["p95"], 300, "Message search p95 > 300ms")
def test_message_upsert_throughput(self):
"""Measure message upsert throughput simulates saving drafts rapidly."""
"""Measure message upsert throughput: simulates saving drafts rapidly."""
print("\n[Messages] Upsert throughput (draft saves):")
durations = []
peer = secrets.token_hex(16)
@ -462,7 +462,7 @@ class TestPerformanceHotPaths(unittest.TestCase):
self.assertLess(stats["p95"], 10, "Message upsert p95 > 10ms")
def test_message_upsert_update_throughput(self):
"""Measure message UPDATE throughput re-saving existing messages (state changes)."""
"""Measure message UPDATE throughput: re-saving existing messages (state changes)."""
print("\n[Messages] Update existing messages:")
peer = secrets.token_hex(16)
msgs = []
@ -487,7 +487,7 @@ class TestPerformanceHotPaths(unittest.TestCase):
)
# ===================================================================
# CONCURRENT WRITERS contention stress
# CONCURRENT WRITERS: contention stress
# ===================================================================
def test_concurrent_message_writers(self):
@ -584,7 +584,7 @@ class TestPerformanceHotPaths(unittest.TestCase):
)
def test_concurrent_read_write_contention(self):
"""Writers inserting while readers query simulates real app usage."""
"""Writers inserting while readers query: simulates real app usage."""
print("\n[Contention] Mixed read/write:")
num_writers = 4
num_readers = 4
@ -673,7 +673,7 @@ class TestPerformanceHotPaths(unittest.TestCase):
self.assertLess(ms_con, 50, "Contacts LIKE search > 50ms")
# ===================================================================
# N+1 BATCH OPERATIONS transaction wrapping regression tests
# N+1 BATCH OPERATIONS: transaction wrapping regression tests
# ===================================================================
def test_mark_conversations_as_read_batch(self):
@ -732,7 +732,7 @@ class TestPerformanceHotPaths(unittest.TestCase):
)
# ===================================================================
# INDEX VERIFICATION confirm new indexes are used
# INDEX VERIFICATION: confirm new indexes are used
# ===================================================================
def test_indexes_exist(self):
@ -782,7 +782,7 @@ class TestPerformanceHotPaths(unittest.TestCase):
self.assertLessEqual(cache_size, -8000)
# ===================================================================
# QUERY PLAN CHECKS confirm indexes are actually used
# QUERY PLAN CHECKS: confirm indexes are actually used
# ===================================================================
def test_query_plan_messages_by_peer(self):

View file

@ -73,7 +73,7 @@ async function mountSettingsPage(api, router = { push: vi.fn() }) {
return wrapper;
}
describe("SettingsPage config persistence (PATCH and related)", () => {
describe("SettingsPage: config persistence (PATCH and related)", () => {
let serverConfigRef;
let api;
@ -486,7 +486,7 @@ describe("SettingsPage — config persistence (PATCH and related)", () => {
});
});
describe("SettingsPage transport mode (POST, not PATCH)", () => {
describe("SettingsPage: transport mode (POST, not PATCH)", () => {
let serverConfigRef;
let api;
@ -516,7 +516,7 @@ describe("SettingsPage — transport mode (POST, not PATCH)", () => {
});
});
describe("SettingsPage visualiser display prefs (localStorage + emitter)", () => {
describe("SettingsPage: visualiser display prefs (localStorage + emitter)", () => {
let serverConfigRef;
let api;
@ -578,7 +578,7 @@ describe("SettingsPage — visualiser display prefs (localStorage + emitter)", (
});
});
describe("SettingsPage maintenance, exports, telemetry trust, RNS reload", () => {
describe("SettingsPage: maintenance, exports, telemetry trust, RNS reload", () => {
let serverConfigRef;
let api;